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.