Преобразование кортежа в список и обратно

В настоящее время я работаю над редактором карт для игры в pygame, используя карты тайлов. Уровень построен из блоков в следующей структуре (хотя и намного больше):

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

Но так как уровень хранится в кортеже, я не могу изменить значения разных блоков. Как мне легко изменить различные значения на уровне?

Ответ 1

Преобразовать кортеж в список:

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

Ответ 2

У вас есть кортеж кортежей.
Чтобы преобразовать каждый кортеж в список:

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

Вы также можете использовать массив 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]])

Для управления:

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

Ответ 3

У вас может быть список списков. Преобразуйте кортеж кортежей в список списков, используя:

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

или

level1 = map(list, level1)

и соответствующим образом изменить их.

Но массив numpy является более прохладным.

Ответ 4

Чтобы преобразовать кортежи в список

(Запятые отсутствовали между кортежами в заданном вопросе, он был добавлен для предотвращения сообщения об ошибке)

Способ 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 секунд ---

Ответ 5

Почему бы вам не попробовать преобразовать свой тип из кортежа в список и наоборот.

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)

Ответ 6

Оба ответа хороши, но небольшой совет:

Кортежи неизменяемы, что означает, что они не могут быть изменены. Поэтому, если вам нужно манипулировать данными, лучше хранить данные в списке, это уменьшит ненужные служебные данные.

В вашем случае извлеките данные в список, как показано eumiro, и после модификации создайте аналогичный кортеж аналогичной структуры, такой как ответ, предоставленный Schoolboy.

Также, как предложено использование массива numpy, это лучший вариант

Ответ 7

Вы могли бы значительно ускорить работу, если бы вы использовали только один список, а не список списков. Это возможно, конечно, только если все ваши внутренние списки имеют одинаковый размер (что верно в вашем примере, поэтому я просто предполагаю это).

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, конечно. Если вам нужно больше значений, вам придется объединить несколько бит, что значительно затруднит проблему.

Ответ 8

Список к кортежу и обратно можно сделать как ниже

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)