关于python:将tuple转换为list和back

Convert tuple to list and back

我目前正在为Pygame中的游戏开发地图编辑器,使用平铺地图。该层由以下结构中的块组成(尽管要大得多):

1
2
3
4
5
6
7
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"是一块空的。

以下代码基本上是处理块类型更改的代码:

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

但由于级别存储在元组中,所以我无法更改不同块的值。如何轻松地更改级别中的不同值?


将元组转换为列表:

1
2
3
4
5
>>> t = ('my', 'name', 'is', 'mr', 'tuple')
>>> t
('my', 'name', 'is', 'mr', 'tuple')
>>> list(t)
['my', 'name', 'is', 'mr', 'tuple']

将列表转换为元组:

1
2
3
4
5
>>> l = ['my', 'name', 'is', 'mr', 'list']
>>> l
['my', 'name', 'is', 'mr', 'list']
>>> tuple(l)
('my', 'name', 'is', 'mr', 'list')


你有一个元组。要将每个元组转换为列表:

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

---或者---

1
map(list, level)

编辑完成后,只需将它们转换回:

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

---或---(谢谢@jamilak)

1
tuple(itertools.imap(tuple, edited))

还可以使用numpy数组:

1
2
3
4
5
6
7
8
>>> 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]])

用于操作:

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


你可以有一个列表。使用以下方法将元组的元组转换为列表列表:

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

1
level1 = map(list, level1)

并进行相应的修改。

但麻木的阵列更酷。


将元组转换为列表

(给定问题中的元组之间缺少逗号,已添加该逗号以防止出现错误消息)

方法1:

1
2
3
4
5
6
7
8
9
10
11
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:

1
2
3
level1 = map(list,level1)

print(list(level1))

方法1用时---0.0019991397857666016秒---

方法2用时---0.0010001659393310547秒---


为什么不尝试将其类型从元组转换为列表,反之亦然。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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)

两个答案都很好,但有一点建议:

元组是不可变的,这意味着它们不能更改。因此,如果需要操作数据,最好将数据存储在列表中,这样可以减少不必要的开销。

在您的例子中,将数据提取到一个列表中,如Eumiro所示,在修改之后,创建一个结构类似的元组,就像小学生给出的答案一样。

同样建议使用numpy数组是更好的选择


如果你只使用一个列表而不是一个列表,你可以极大地加快你的工作速度。当然,只有当所有内部列表的大小相同时(在您的示例中是这样的,所以我假设是这样的),这才是可能的。

1
2
3
4
5
6
7
8
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)

如果使用位字段而不是列表,则速度可能更快:

1
2
3
4
5
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)

具有

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

但是,只有当字段只包含0或1时,这才有效。如果你需要更多的值,你必须结合几个位,这将使问题更加复杂。


列表到tuple和back的操作如下

1
2
3
4
5
6
7
8
9
10
11
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)