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