Перетворення кортежу в список і назад


206

Зараз я працюю над редактором карт для гри в пігамі, використовуючи карти плиток. Рівень побудований з блоків у такій структурі (хоча і значно більшої):

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

де "1" - це стіна, а "0" - це порожній повітря.

Наступний код є в основному тим, хто обробляє зміну типу блоку:

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

Але оскільки рівень зберігається в кортежі, я не можу змінити значення різних блоків. Як мені легко змінити різні значення в рівні?


12
не використовуйте кортеж, просто використовуйте список з самого початку. Це дійсно може уповільнити ваш код, якщо ваш рівень величезний, якщо вам доведеться продовжувати їх перетворювати
jamylak

4
як щодо того, щоб з самого початку йти зі списками замість кортежів?
Krzysztof Bujniewicz

4
@ user2133308 btw лише примітка про сумісність, ви повинні використовувати ціле ділення //замість того, що лише /в Python 3 /буде виконуватися поділ з плаваючою комою та викручується ваш код.
jamylak

Відповіді:


284

Перетворити кортеж у список:

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

Перетворити список для кортежу:

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

5
Це не працює для мене. Якщо я запускаю код у першому блоці для перетворення кортежу t у список, передаючи t у список (), я отримую повідомлення про помилку: "*** Помилка в аргументі: '(t)'" Це, мабуть, трапляється мене лише під час налагодження. Ще розгублений.
Джиммі

4
@Jimmy це тому, що список є командою налагодження, запустіть p list(...)замість цього.
moritz

74

У вас є кортеж кортежів.
Щоб конвертувати кожен кортеж у список:

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

--- АБО ---

map(list, level)

І після того, як ви закінчите редагування, просто перетворіть їх назад:

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

--- АБО --- (спасибі @jamylak)

tuple(itertools.imap(tuple, edited))

Ви також можете використовувати масивний масив:

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

Для маніпулювання:

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

2
NumPy - основний пакет наукових обчислень з Python. Основним об'єктом NumPy є однорідний багатовимірний масив. Це таблиця елементів (зазвичай чисел), всіх однотипних, індексованих набором натуральних чисел.
pradyunsg

24

Ви можете мати список списків. Перетворіть свій набір кортежів у список списків, використовуючи:

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

або

level1 = map(list, level1)

і відповідно модифікувати їх.

Але нумерований масив крутіший.


18

Для перетворення кортежів у список

(Коми пропущені між кортежами в даному запитанні, воно було додано для запобігання повідомлення про помилку)

Спосіб 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)

Спосіб 2:

level1 = map(list,level1)

print(list(level1))

Спосіб 1 зайняв --- 0,0019991397857666016 секунд ---

Спосіб 2 зайняв --- 0,0010001659393310547 секунд ---


14

Чому б вам не спробувати перетворити його тип з кортежу в список і навпаки.

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

Обидві відповіді хороші, але невелика порада:

Кортежі незмінні, що означає, що їх неможливо змінити. Тож якщо вам потрібно маніпулювати даними, краще зберігати дані у списку, це зменшить зайві накладні витрати.

У вашому випадку витягніть дані до списку, як показав eumiro, і після модифікації створіть схожий набір подібної структури, як відповідь, яку дав Школяр.

Також, як пропонується використовувати numpy масив, є кращим варіантом


Ви також повинні написати в цій відповіді, що numpyзабезпечить найшвидше рішення для роботи з цим типом даних.
jamylak

Звичайно, ви можете використовувати незмінні структури даних, наприклад кортежі, навіть коли ви маніпулюєте даними. Вся передумова функціонального програмування та все, що багато в чому будується на постійності даних. Але звичайно, на землі Python ви можете ходити з масами і вільно мутувати ...
nperson325681

5

Список до Tuple і назад можна зробити, як показано нижче

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

Ви могли б значно пришвидшити свої речі, якщо замість списку використали лише один список. Це можливо, звичайно, лише якщо всі ваші внутрішні списки однакового розміру (що справедливо у вашому прикладі, тому я просто припускаю це).

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)

І ви можете бути ще швидшими, якщо замість списку використали бітфілд:

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)

з

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

Але це працює лише в тому випадку, якщо ваші поля містять 0 або 1 звичайно. Якщо вам потрібно більше значень, вам доведеться поєднувати кілька біт, що ускладнить проблему.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.