Converter tupla em lista e voltar

206

Atualmente, estou trabalhando em um editor de mapas para um jogo em pygame, usando mapas de blocos. O nível é construído a partir de blocos na seguinte estrutura (embora muito maior):

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))

onde "1" é um bloco que é uma parede e "0" é um bloco que é ar vazio.

O código a seguir é basicamente aquele que lida com a alteração do tipo de bloco:

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

Mas como o nível é armazenado em uma tupla, não consigo alterar os valores dos diferentes blocos. Como faço para alterar os diferentes valores no nível de maneira fácil?

user2133308
fonte
12
não use uma tupla, basta usar uma lista desde o início. Ele pode realmente abrandar o seu código se o seu nível é enorme, se você tem que manter convertê-los
jamylak
4
que tal ir com listas em vez de tuplas desde o início?
Krzysztof Bujniewicz 30/04
4
@ user2133308 btw apenas uma nota de compatibilidade, você deve usar a divisão inteira ao //invés de apenas /porque, no Python 3, /realizará a divisão de ponto flutuante e estragará seu código.
jamylak

Respostas:

284

Converter tupla em lista:

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

Converter lista em tupla:

>>> l = ['my', 'name', 'is', 'mr', 'list']
>>> l
['my', 'name', 'is', 'mr', 'list']
>>> tuple(l)
('my', 'name', 'is', 'mr', 'list')
Khonix
fonte
5
Isso não está funcionando para mim. Se eu executar o código no primeiro bloco para converter a tupla t em uma lista passando t para list (), recebo uma mensagem de erro: "*** Erro no argumento: '(t)'" Isso parece acontecer com eu apenas durante a depuração. Ainda confuso.
Jimmy
4
@ Jimmy, porque list é um comando debugger, execute em p list(...)vez disso.
Moritz
74

Você tem uma tupla de tuplas.
Para converter todas as tuplas em uma lista:

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

--- OU ---

map(list, level)

E depois que você terminar de editar, basta convertê-los de volta:

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

--- OU --- (Obrigado @jamylak)

tuple(itertools.imap(tuple, edited))

Você também pode usar uma 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
fonte
2
O NumPy é o pacote fundamental para a computação científica com Python. O principal objeto do NumPy é a matriz multidimensional homogênea. É uma tabela de elementos (geralmente números), todos do mesmo tipo, indexados por uma tupla de números inteiros positivos.
precisa saber é
24

Você pode ter uma lista de listas. Converta sua tupla de tuplas em uma lista de listas usando:

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

ou

level1 = map(list, level1)

e modifique-os de acordo.

Mas uma matriz numpy é mais fria.

eumiro
fonte
18

Para converter tuplas em lista

(Faltava vírgulas entre as tuplas na pergunta especificada e foi adicionada para evitar mensagens de erro)

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))

O método 1 levou --- 0,0019991397857666016 segundos ---

O método 2 levou --- 0,0010001659393310547 segundos ---

Aravind Krishnakumar
fonte
14

Por que você não tenta converter seu tipo de uma tupla para uma lista e vice-versa.

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
fonte
5

Ambas as respostas são boas, mas um pequeno conselho:

As tuplas são imutáveis, o que implica que elas não podem ser alteradas. Portanto, se você precisar manipular dados, é melhor armazenar dados em uma lista, pois isso reduzirá a sobrecarga desnecessária.

No seu caso, extraia os dados para uma lista, como mostrado por eumiro, e depois da modificação, crie uma tupla semelhante de estrutura semelhante à resposta dada pelo aluno.

Também como sugerido usando a matriz numpy é uma opção melhor

tanzil
fonte
Você também deve escrever nesta resposta, que numpyfornecerá a solução mais rápida para trabalhar com esse tipo de dados.
jamylak
Obviamente, você pode usar estruturas de dados imutáveis, como tuplas, mesmo quando estiver manipulando dados. Toda a premissa da programação funcional e tudo o que se baseia amplamente na persistência dos dados. Mas, claro, na terra Python você pode querer ir com as massas e transformar livremente ...
nperson325681
5

A lista para Tupla e vice-versa pode ser feita conforme abaixo

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
fonte
2

Você poderia acelerar drasticamente suas coisas se usasse apenas uma lista em vez de uma lista de listas. Obviamente, isso só é possível se todas as suas listas internas tiverem o mesmo tamanho (o que é verdade no seu exemplo, então eu assumo isso).

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 você poderia ser ainda mais rápido se usasse um campo de bits em vez de uma 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)

com

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

Mas isso funcionará apenas se seus campos contiverem 0 ou 1, é claro. Se você precisar de mais valores, precisará combinar vários bits, o que tornaria o problema muito mais complicado.

Alfe
fonte