Converti la tupla in elenco e viceversa


207

Attualmente sto lavorando a un editor di mappe per un gioco in pygame, usando le mappe delle tessere. Il livello è costituito da blocchi nella seguente struttura (anche se molto più grande):

level1 = (
         (1,1,1,1,1,1)
         (1,0,0,0,0,1)
         (1,0,0,0,0,1)
         (1,0,0,0,0,1)
         (1,0,0,0,0,1)
         (1,1,1,1,1,1))

dove "1" è un blocco che è un muro e "0" è un blocco che è aria vuota.

Il seguente codice è sostanzialmente quello che gestisce la modifica del tipo di blocco:

clicked = pygame.mouse.get_pressed()
if clicked[0] == 1:
    currLevel[((mousey+cameraY)/60)][((mousex+cameraX)/60)] = 1

Ma poiché il livello è memorizzato in una tupla, non sono in grado di modificare i valori dei diversi blocchi. Come posso cambiare i diversi valori nel livello in modo semplice?


12
non usare una tupla, basta usare un elenco dall'inizio. Potrebbe davvero rallentare il tuo codice se il tuo livello è enorme, se devi continuare a convertirli
— jamylak,

4
che ne dici di andare con le liste invece delle tuple fin dall'inizio?
— Krzysztof Bujniewicz,

4
@utente2133308 a proposito solo una nota di compatibilità, dovresti usare la divisione intera //invece che solo /perché in Python 3 /eseguirà la divisione in virgola mobile e rovinerà il tuo codice.
— jamylak,

Risposte:


285

Converti tupla in elenco:

>>> t = ('my', 'name', 'is', 'mr', 'tuple')
>>> t
('my', 'name', 'is', 'mr', 'tuple')
>>> list(t)
['my', 'name', 'is', 'mr', 'tuple']

Converti elenco in tupla:

>>> l = ['my', 'name', 'is', 'mr', 'list']
>>> l
['my', 'name', 'is', 'mr', 'list']
>>> tuple(l)
('my', 'name', 'is', 'mr', 'list')

6
Questo non funziona per me. Se eseguo il codice nel primo blocco per convertire la tupla t in un elenco passando t a list (), viene visualizzato un messaggio di errore: "*** Errore nell'argomento: '(t)'" Questo sembra accadere a solo durante il debug. Ancora confuso.
— Jimmy,

5
@Jimmy questo perché list è un comando debugger, esegui p list(...)invece.
— Moritz,

74

Hai una tupla di tuple.
Per convertire ogni tupla in un elenco:

[list(i) for i in level] # list of lists

--- O ---

map(list, level)

E dopo aver terminato la modifica, è sufficiente riconvertirli:

tuple(tuple(i) for i in edited) # tuple of tuples

--- OPPURE --- (Grazie @jamylak)

tuple(itertools.imap(tuple, edited))

Puoi anche usare una matrice numpy:

>>> a = numpy.array(level1)
>>> a
array([[1, 1, 1, 1, 1, 1],
       [1, 0, 0, 0, 0, 1],
       [1, 0, 0, 0, 0, 1],
       [1, 0, 0, 0, 0, 1],
       [1, 0, 0, 0, 0, 1],
       [1, 1, 1, 1, 1, 1]])

Per manipolare:

if clicked[0] == 1:
    x = (mousey + cameraY) // 60 # For readability
    y = (mousex + cameraX) // 60 # For readability
    a[x][y] = 1

2
NumPy è il pacchetto fondamentale per l'elaborazione scientifica con Python. L'oggetto principale di NumPy è l'array multidimensionale omogeneo. È una tabella di elementi (solitamente numeri), tutti dello stesso tipo, indicizzati da una tupla di numeri interi positivi.
— pradyunsg,

24

Puoi avere un elenco di liste. Converti la tua tupla di tuple in un elenco di elenchi utilizzando:

level1 = [list(row) for row in level1]

o

level1 = map(list, level1)

e modificarli di conseguenza.

Ma un array intorpidito è più interessante.


18

Per convertire le tuple in elenco

(Mancavano le virgole tra le tuple nella domanda data, è stato aggiunto per evitare un messaggio di errore)

Metodo 1:

level1 = (
     (1,1,1,1,1,1),
     (1,0,0,0,0,1),
     (1,0,0,0,0,1),
     (1,0,0,0,0,1),
     (1,0,0,0,0,1),
     (1,1,1,1,1,1))

level1 = [list(row) for row in level1]

print(level1)

Metodo 2:

level1 = map(list,level1)

print(list(level1))

Il metodo 1 ha richiesto --- 0,0019991397857666016 secondi ---

Il metodo 2 ha richiesto --- 0,0010001659393310547 secondi ---


14

Perché non provi a convertire il suo tipo da una tupla a un elenco e viceversa.

level1 = (
     (1,1,1,1,1,1)
     (1,0,0,0,0,1)
     (1,0,0,0,0,1)
     (1,0,0,0,0,1)
     (1,0,0,0,0,1)
     (1,1,1,1,1,1))

print(level1)

level1 = list(level1)

print(level1)

level1 = tuple(level1)

print(level1)

5

Entrambe le risposte sono buone, ma un piccolo consiglio:

Le tuple sono immutabili, il che implica che non possono essere cambiate. Quindi, se è necessario manipolare i dati, è meglio archiviare i dati in un elenco, ridurrà il sovraccarico non necessario.

Nel tuo caso estrai i dati in un elenco, come mostrato da eumiro, e dopo averlo modificato crea una tupla simile di struttura simile alla risposta data da Schoolboy.

Anche come suggerito l'uso dell'array numpy è un'opzione migliore


Dovresti anche scrivere in questa risposta, che numpyfornirà la soluzione più veloce per lavorare con questo tipo di dati.
— jamylak,

Ovviamente puoi usare strutture di dati immutabili come le tuple anche quando stai manipolando i dati. L'intera premessa della programmazione funzionale e tutto ciò che si basa in gran parte sulla persistenza dei dati. Ma ovviamente, nella terra di Python potresti voler andare con le masse e mutare liberamente ...
— nperson325681

5

L'elenco su Tupla e ritorno può essere fatto come di seguito

import ast, sys
input_str = sys.stdin.read()
input_tuple = ast.literal_eval(input_str)

l = list(input_tuple)
l.append('Python')
#print(l)
tuple_2 = tuple(l)

# Make sure to name the final tuple 'tuple_2'
print(tuple_2)

2

Potresti velocizzare notevolmente le tue cose se usassi solo un elenco invece di un elenco di elenchi. Questo è ovviamente possibile solo se tutti i tuoi elenchi interni hanno le stesse dimensioni (il che è vero nel tuo esempio, quindi presumo solo questo).

WIDTH = 6
level1 = [ 1,1,1,1,1,1,
           1,0,0,0,0,1,
           1,0,0,0,0,1,
           1,0,0,0,0,1,
           1,0,0,0,0,1,
           1,1,1,1,1,1 ]
print level1[x + y*WIDTH]  # print value at (x,y)

E potresti essere ancora più veloce se utilizzassi un bitfield anziché un elenco:

WIDTH = 8  # better align your width to bytes, eases things later
level1 = 0xFC84848484FC  # bit field representation of the level
print "1" if level1 & mask(x, y) else "0"  # print bit at (x, y)
level1 |= mask(x, y)  # set bit at (x, y)
level1 &= ~mask(x, y)  # clear bit at (x, y)

con

def mask(x, y):
  return 1 << (WIDTH-x + y*WIDTH)

Ma funziona solo se i tuoi campi contengono solo 0 o 1 ovviamente. Se hai bisogno di più valori, dovresti combinare diversi bit che renderebbero il problema molto più complicato.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.