2013-04-30 3 views
98

В настоящее время я работаю над редактором карт для игры в 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 

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

Редактировать: Решено! Спасибо, ребята

+9

не использовать кортеж, просто использовать список с самого начала. Это может действительно замедлить ваш код, если ваш уровень огромен, если вам нужно продолжать конвертировать их – jamylak

+3

, как насчет того, чтобы идти с списками вместо кортежей с самого начала? –

+3

@ user2133308 btw просто примечание о совместимости, вы должны использовать целочисленное деление '//' вместо просто '/', потому что в Python 3 '/' будет выполнять разделение с плавающей запятой и испортить ваш код. – jamylak

ответ

17

У вас может быть список списков. Преобразование кортеж кортежей в список списков с помощью:

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

или

level1 = map(list, level1) 

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

Но numpy array более прохладный.

50

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

[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 
+0

Что это за массив numpy? объясните пожалуйста. – eRaisedToX

+0

NumPy - это фундаментальный пакет для научных вычислений с Python. Основной объект NumPy - это однородный многомерный массив. Это таблица элементов (обычно чисел), всех одинаковых типов, индексированных кортежем положительных целых чисел. – pradyunsg

4

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

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

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

Кроме того, как предложил использовать Numpy массив является лучшим вариантом

+0

Вы также должны написать в этом ответе, что 'numpy' обеспечит самое быстрое решение для работы с данным типом данных. – jamylak

+0

Конечно, вы можете использовать неизменяемые структуры данных, такие как кортежи, даже когда вы манипулируете данными. Вся предпосылка функционального программирования и все это в значительной степени основывается на сохранении данных. Но, конечно, на земле Питона вы можете пойти с массами и свободно мутировать ... – progo

1

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

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

148

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

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

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

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

Блестящая идея! –

10

Для преобразования кортежей в список

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

Метод 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 секунд ---

Смежные вопросы