2013-04-30 12 views
98

Attualmente sto lavorando a un editor di mappe per un gioco in pygame, utilizzando mappe di tile. Il livello è costruita su blocchi nella seguente struttura (anche se molto più grande):Converti tuple in elenco e ritorno

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 è vuoto.

Il seguente codice è fondamentalmente la gestione del cambio di tipo di blocco uno:

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, sono in grado di modificare i valori dei vari blocchi. Come faccio a cambiare i diversi valori nel livello in modo semplice?

Modifica: risolto! Grazie ragazzi

+9

non utilizzare un tuple, basta usare un elenco dall'inizio. Potrebbe davvero rallentare il tuo codice se il tuo livello è enorme, se devi continuare a convertirli – jamylak

+3

come fare con le liste invece delle tuple fin dall'inizio? –

+3

@ user2133308 btw solo una nota di compatibilità, dovresti usare la divisione integer '//' invece di solo '/' perché in Python 3, '/' eseguirà la divisione in virgola mobile e rovinerà il tuo codice. – jamylak

risposta

17

È possibile avere un elenco di elenchi. Converti il ​​tuo tuple di tuple a una lista di liste che utilizzano:

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

o

level1 = map(list, level1) 

e modificare di conseguenza.

Ma uno numpy array è più freddo.

50

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

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

--- O ---

map(list, level) 

E dopo aver terminato l'editing, basta riconvertire:

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

--- OR --- (Grazie @jamylak)

tuple(itertools.imap(tuple, edited)) 

È inoltre possibile utilizzare un array 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 la manipolazione:

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

cos'è questa matrice numpy? spiegare per favore .. – eRaisedToX

+0

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

4

Entrambe le risposte sono buone, ma un piccolo consiglio:

tuple sono immutabile, il che implica che non possono essere modificati. Quindi, se hai bisogno di manipolare i dati, è meglio memorizzare i dati in un elenco, ridurrà i costi non necessari.

Nel tuo caso estrai i dati in un elenco, come mostrato da eumiro, e dopo aver modificato crea una tupla simile di struttura simile a quella data dallo Scolaro.

anche come ha suggerito di utilizzare array di NumPy è una scelta migliore

+0

Si dovrebbe anche scrivere in questa risposta, che 'numpy' fornirà la soluzione più veloce per lavorare con questo tipo di dati. – jamylak

+0

Ovviamente è possibile utilizzare strutture di dati immutabili come tuple anche quando si manipolano i dati. L'intera premessa della programmazione funzionale e tutto ciò in gran parte si basa sulla persistenza dei dati. Ma ovviamente, in Python land potresti voler andare con le masse e mutare liberamente ... – progo

1

Si potrebbe notevolmente accelerare la roba se si è utilizzato una sola lista, invece di una lista di liste. Questo è ovviamente possibile solo se tutti i tuoi elenchi interni hanno la stessa dimensione (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 si potrebbe essere ancora più veloce se si è utilizzato un campo di bit al posto di una lista:

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 questo è lavorare solo se i campi contengono solo 0 o 1 ovviamente. Se hai bisogno di più valori, dovresti combinare diversi bit che renderebbero il problema molto più complicato.

148

Converti tuple alla lista:

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

elenco Converti in tuple:

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

Perché non provare la conversione il tipo da una tupla a una lista 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) 
+0

Brilliant Idea! –

10

Per convertire tuple alla lista

(virgole mancavano tra le tuple in data domanda, è stato aggiunto per evitare che il 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)) 

Metodo 1 ha avuto --- --- 0.0019991397857666016 secondi

Metodo 2 prese --- --- 0.0010001659393310547 secondi