Convertir le tuple en liste et inversement


207

Je travaille actuellement sur un éditeur de carte pour un jeu en pygame, en utilisant des cartes de tuiles. Le niveau est construit à partir de blocs dans la structure suivante (bien que beaucoup plus 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))

où "1" est un bloc qui est un mur et "0" est un bloc qui est de l'air vide.

Le code suivant est essentiellement celui qui gère le changement de type de bloc:

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

Mais comme le niveau est stocké dans un tuple, je ne peux pas changer les valeurs des différents blocs. Comment changer facilement les différentes valeurs du niveau?


12
n'utilisez pas de tuple, utilisez simplement une liste depuis le début. Cela pourrait vraiment ralentir votre code si votre niveau est énorme, si vous devez continuer à les convertir
jamylak

4
que diriez-vous d'aller avec des listes au lieu de tuples dès le début?
Krzysztof Bujniewicz

4
@ user2133308 btw juste une note de compatibilité, vous devez utiliser la division entière //au lieu de simplement /parce que dans Python 3, /effectuera la division en virgule flottante et bousiller votre code.
jamylak

Réponses:


285

Convertir le tuple en liste:

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

Convertir la liste en tuple:

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

6
Cela ne fonctionne pas pour moi. Si j'exécute le code dans le premier bloc pour convertir le tuple t en liste en passant t à list (), j'obtiens un message d'erreur: "*** Erreur dans l'argument: '(t)'" Cela semble arriver à moi seulement lors du débogage. Encore confus.
Jimmy

5
@Jimmy c'est parce que list est une commande de débogage, exécutez-la à la p list(...)place.
moritz

74

Vous avez un tuple de tuples.
Pour convertir chaque tuple en liste:

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

--- OU ---

map(list, level)

Et une fois l'édition terminée, il vous suffit de les reconvertir:

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

--- OU --- (Merci @jamylak)

tuple(itertools.imap(tuple, edited))

Vous pouvez également utiliser un tableau 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]])

Pour manipuler:

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

2
NumPy est le package fondamental pour le calcul scientifique avec Python. L'objet principal de NumPy est le tableau multidimensionnel homogène. Il s'agit d'une table d'éléments (généralement des nombres), tous du même type, indexés par un tuple d'entiers positifs.
pradyunsg

24

Vous pouvez avoir une liste de listes. Convertissez votre tuple de tuples en une liste de listes en utilisant:

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

ou

level1 = map(list, level1)

et modifiez-les en conséquence.

Mais un tableau numpy est plus cool.


18

Pour convertir des tuples en liste

(Des virgules manquaient entre les tuples dans la question donnée, elle a été ajoutée pour éviter le message d'erreur)

Méthode 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éthode 2:

level1 = map(list,level1)

print(list(level1))

La méthode 1 a pris --- 0,0019991397857666016 secondes ---

La méthode 2 a pris --- 0,0010001659393310547 secondes ---


14

Pourquoi n'essayez-vous pas de convertir son type d'un tuple en une liste et 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)

5

Les deux réponses sont bonnes, mais un petit conseil:

Les tuples sont immuables, ce qui implique qu'ils ne peuvent pas être modifiés. Donc, si vous avez besoin de manipuler des données, il est préférable de stocker les données dans une liste, cela réduira les frais généraux inutiles.

Dans votre cas, extrayez les données dans une liste, comme indiqué par eumiro, et après modification, créez un tuple similaire de structure similaire à la réponse donnée par Schoolboy.

Aussi, comme suggéré, l'utilisation du tableau numpy est une meilleure option


Vous devez également écrire dans cette réponse, qui numpyfournira la solution la plus rapide pour travailler avec ce type de données.
jamylak

Bien sûr, vous pouvez utiliser des structures de données immuables telles que des tuples même lorsque vous manipulez des données. Toute la prémisse de la programmation fonctionnelle et tout ce qui repose en grande partie sur la persistance des données. Mais bien sûr, en Python, vous voudrez peut-être aller avec les masses et muter librement ...
nperson325681

5

La liste des tuple et retour peut être effectuée comme ci-dessous

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

Vous pouvez accélérer considérablement vos affaires si vous utilisez une seule liste au lieu d'une liste de listes. Ceci n'est bien sûr possible que si toutes vos listes internes sont de la même taille (ce qui est vrai dans votre exemple, donc je suppose cela).

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)

Et vous pourriez être encore plus rapide si vous utilisiez un champ de bits au lieu d'une liste:

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)

avec

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

Mais cela ne fonctionne que si vos champs contiennent juste 0 ou 1 bien sûr. Si vous avez besoin de plus de valeurs, vous devrez combiner plusieurs bits, ce qui rendrait le problème beaucoup plus compliqué.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.