Convierte tuplas a la lista y viceversa

207

Actualmente estoy trabajando en un editor de mapas para un juego en pygame, usando mapas en mosaico. El nivel se construye a partir de bloques en la siguiente estructura (aunque mucho más 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))

donde "1" es un bloque que es una pared y "0" es un bloque que está vacío.

El siguiente código es básicamente el que maneja el cambio de tipo de bloque:

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

Pero como el nivel se almacena en una tupla, no puedo cambiar los valores de los diferentes bloques. ¿Cómo hago para cambiar los diferentes valores en el nivel de una manera fácil?

usuario2133308
fuente
12
no uses una tupla, solo usa una lista desde el principio. Realmente podría ralentizar su código si su nivel es enorme, si tiene que seguir convirtiéndolos
jamylak
44
¿Qué tal ir con listas en lugar de tuplas desde el principio?
Krzysztof Bujniewicz
44
@ user2133308 por cierto solo una nota de compatibilidad, debe usar la división de enteros en //lugar de solo /porque en Python 3, /realizará una división de punto flotante y arruinará su código.
jamylak

Respuestas:

285

Convertir tupla a la lista:

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

Convertir lista a tupla:

>>> l = ['my', 'name', 'is', 'mr', 'list']
>>> l
['my', 'name', 'is', 'mr', 'list']
>>> tuple(l)
('my', 'name', 'is', 'mr', 'list')
Khonix
fuente
66
Esto no está funcionando para mí. Si ejecuto el código en el primer bloque para convertir la tupla t en una lista pasando t to list (), recibo un mensaje de error: "*** Error en el argumento: '(t)'" Esto parece suceder a yo solo durante la depuración. Sigo confundido.
Jimmy
55
@Jimmy es porque la lista es un comando de depuración, ejecuta en su p list(...)lugar.
moritz
74

Tienes una tupla de tuplas.
Para convertir cada tupla en una lista:

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

--- O ---

map(list, level)

Y una vez que haya terminado de editar, simplemente conviértalos de nuevo:

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

--- O --- (Gracias @jamylak)

tuple(itertools.imap(tuple, edited))

También puede usar una matriz 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]])

Para manipular:

if clicked[0] == 1:
    x = (mousey + cameraY) // 60 # For readability
    y = (mousex + cameraX) // 60 # For readability
    a[x][y] = 1
pradyunsg
fuente
2
NumPy es el paquete fundamental para la computación científica con Python. El objeto principal de NumPy es la matriz multidimensional homogénea. Es una tabla de elementos (generalmente números), todos del mismo tipo, indexados por una tupla de enteros positivos.
pradyunsg
24

Puedes tener una lista de listas. Convierta su tupla de tuplas en una lista de listas usando:

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

o

level1 = map(list, level1)

y modificarlos en consecuencia.

Pero una matriz numpy es más fresca.

eumiro
fuente
18

Para convertir tuplas a la lista

(Faltaban comas entre las tuplas en la pregunta dada, se agregó para evitar mensajes de error)

Método 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)

Método 2:

level1 = map(list,level1)

print(list(level1))

El método 1 tomó --- 0.0019991397857666016 segundos ---

El método 2 tomó --- 0.0010001659393310547 segundos ---

Aravind Krishnakumar
fuente
14

¿Por qué no intentas convertir su tipo de una tupla a una lista y 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)
TheRedstoneLemon
fuente
5

Ambas respuestas son buenas, pero un pequeño consejo:

Las tuplas son inmutables, lo que implica que no se pueden cambiar. Entonces, si necesita manipular datos, es mejor almacenarlos en una lista, ya que reducirá los gastos innecesarios.

En su caso, extraiga los datos en una lista, como lo muestra eumiro, y después de modificar, cree una tupla similar de estructura similar a la respuesta dada por Schoolboy.

También como se sugiere usar numpy array es una mejor opción

tanzil
fuente
También debe escribir en esta respuesta, que numpyproporcionará la solución más rápida para trabajar con este tipo de datos.
jamylak
Por supuesto, puede usar estructuras de datos inmutables, como tuplas, incluso cuando está manipulando datos. Toda la premisa de la programación funcional y todo lo que se basa en gran medida en la persistencia de los datos. Pero, por supuesto, en Python land es posible que desee ir con las masas y mutar libremente ...
nperson325681
5

La lista para Tupla y viceversa se puede hacer de la siguiente manera

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)
Vijay Rangarajan
fuente
2

Podrías acelerar dramáticamente tus cosas si usaras solo una lista en lugar de una lista de listas. Por supuesto, esto es posible solo si todas sus listas internas son del mismo tamaño (lo cual es cierto en su ejemplo, por lo que asumo esto).

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)

Y podría ser aún más rápido si usara un campo de bits en lugar de 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)

Pero eso solo funciona si sus campos solo contienen 0 o 1, por supuesto. Si necesita más valores, tendría que combinar varios bits, lo que complicaría mucho más el problema.

Alfe
fuente