Konwertuj krotkę na listę iz powrotem

206

Obecnie pracuję nad edytorem map do gry w grze pygame, używając map kafelkowych. Poziom składa się z bloków w następującej strukturze (choć znacznie większej):

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

gdzie „1” to blok, który jest ścianą, a „0” to blok, który jest pustym powietrzem.

Poniższy kod jest w zasadzie tym, który obsługuje zmianę typu bloku:

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

Ale ponieważ poziom jest przechowywany w krotce, nie jestem w stanie zmienić wartości różnych bloków. Jak mogę w prosty sposób zmieniać różne wartości na poziomie?

użytkownik2133308
źródło
12
nie używaj krotki, po prostu użyj listy od początku. Może naprawdę spowolnić twój kod, jeśli Twój poziom jest ogromny, jeśli będziesz musiał je ciągle konwertować
jamylak 30.04.2013
4
co powiesz na chodzenie z listami zamiast krotek od samego początku?
Krzysztof Bujniewicz
4
@ user2133308 btw tylko uwaga na temat zgodności, powinieneś użyć dzielenia liczb całkowitych //zamiast tylko /dlatego, że w Pythonie 3 /wykonasz dzielenie zmiennoprzecinkowe i spieprzysz swój kod.
jamylak 30.04.2013

Odpowiedzi:

284

Konwertuj krotkę na listę:

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

Konwertuj listę na krotkę:

>>> l = ['my', 'name', 'is', 'mr', 'list']
>>> l
['my', 'name', 'is', 'mr', 'list']
>>> tuple(l)
('my', 'name', 'is', 'mr', 'list')
Khonix
źródło
5
To mi nie działa. Jeśli uruchomię kod w pierwszym bloku, aby przekonwertować krotkę t na listę, przekazując t do list (), otrzymuję komunikat o błędzie: „*** Błąd w argumencie:„ (t) ”„ Wygląda na to, że ja tylko podczas debugowania. Wciąż zdezorientowany.
Jimmy
4
@ Jimmy, ponieważ lista jest poleceniem debuggera, uruchom p list(...)zamiast tego.
moritz
74

Masz krotkę krotek.
Aby przekonwertować każdą krotkę na listę:

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

--- LUB ---

map(list, level)

A po zakończeniu edycji po prostu przekonwertuj je z powrotem:

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

--- LUB --- (Dzięki @jamylak)

tuple(itertools.imap(tuple, edited))

Możesz także użyć tablicy 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]])

Do manipulowania:

if clicked[0] == 1:
    x = (mousey + cameraY) // 60 # For readability
    y = (mousex + cameraX) // 60 # For readability
    a[x][y] = 1
pradyunsg
źródło
2
NumPy to podstawowy pakiet do obliczeń naukowych w Pythonie. Głównym celem NumPy jest jednorodna wielowymiarowa tablica. Jest to tabela elementów (zwykle liczb) tego samego typu, indeksowana przez krotkę dodatnich liczb całkowitych.
pradyunsg
24

Możesz mieć listę list. Konwertuj krotkę krotek na listę list, używając:

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

lub

level1 = map(list, level1)

i odpowiednio je zmodyfikuj.

Ale tablica numpy jest fajniejsza.

eumiro
źródło
18

Aby przekonwertować krotki na listę

(Pomiędzy krotkami w danym pytaniu brakowało przecinków, dodano je, aby zapobiec komunikatowi o błędzie)

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

Metoda 2:

level1 = map(list,level1)

print(list(level1))

Metoda 1 zajęła --- 0,0019991397857666016 sekund ---

Metoda 2 zajęła --- 0,0010001659393310547 sekund ---

Aravind Krishnakumar
źródło
14

Dlaczego nie spróbujesz przekonwertować jego typu z krotki na listę i odwrotnie?

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
źródło
5

Obie odpowiedzi są dobre, ale mała rada:

Krotki są niezmienne, co oznacza, że ​​nie można ich zmienić. Więc jeśli musisz manipulować danymi, lepiej przechowywać dane na liście, zmniejszy to niepotrzebny narzut.

W twoim przypadku wyodrębnij dane do listy, jak pokazuje eumiro, a po modyfikacji stwórz podobną krotkę o podobnej strukturze, co odpowiedź udzielona przez Schoolboy.

Również zgodnie z sugestią użycie tablicy numpy jest lepszą opcją

tanzil
źródło
Powinieneś również napisać w tej odpowiedzi, która numpyzapewni najszybsze rozwiązanie do pracy z tego typu danymi.
jamylak 30.04.2013
Oczywiście możesz używać niezmiennych struktur danych, takich jak krotki, nawet gdy manipulujesz danymi. Cała przesłanka programowania funkcjonalnego i wszystko, co w dużej mierze opiera się na trwałości danych. Ale oczywiście w krainie Python możesz iść z masami i swobodnie mutować ...
nperson325681,
5

Listę do Tuple i wstecz można wykonać jak poniżej

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
źródło
2

Możesz znacznie przyspieszyć swoje rzeczy, jeśli użyjesz tylko jednej listy zamiast listy list. Jest to oczywiście możliwe tylko wtedy, gdy wszystkie twoje wewnętrzne listy są tego samego rozmiaru (co jest prawdą w twoim przykładzie, więc po prostu to zakładam).

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)

Możesz być jeszcze szybszy, jeśli użyjesz pola bitowego zamiast listy:

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)

z

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

Ale działa to tylko wtedy, gdy twoje pola zawierają tylko 0 lub 1, oczywiście. Jeśli potrzebujesz więcej wartości, musisz połączyć kilka bitów, co znacznie skomplikuje problem.

Alfe
źródło