我有一个2项元组的列表,我想将它们转换为2个列表,其中第一个包含每个元组中的第一个项目,第二个列表包含第二个项目.
例如:
original = [('a', 1), ('b', 2), ('c', 3), ('d', 4)] # and I want to become... result = (['a', 'b', 'c', 'd'], [1, 2, 3, 4])
是否有内置函数可以做到这一点?
zip
是它自己的逆!如果您使用特殊*运算符.
>>> zip(*[('a', 1), ('b', 2), ('c', 3), ('d', 4)]) [('a', 'b', 'c', 'd'), (1, 2, 3, 4)]
这种方式的工作方式是zip
使用参数调用:
zip(('a', 1), ('b', 2), ('c', 3), ('d', 4))
...除了参数zip
直接传递给(在转换为元组之后),所以不必担心参数的数量太大.
你也可以这样做
result = ([ a for a,b in original ], [ b for a,b in original ])
它应该更好地扩展.特别是如果Python不擅长扩展列表推导,除非需要.
(顺便说一句,它产生了一个2元组(对)列表,而不是像元组列表那样zip
.)
如果生成器而不是实际列表都可以,那么这样做:
result = (( a for a,b in original ), ( b for a,b in original ))
在您询问每个元素之前,生成器不会遍历列表,但另一方面,它们会保留对原始列表的引用.
如果您的列表长度不同,则可能不希望按照Patricks的说法使用zip.这有效:
>>> zip(*[('a', 1), ('b', 2), ('c', 3), ('d', 4)]) [('a', 'b', 'c', 'd'), (1, 2, 3, 4)]
但是使用不同的长度列表,zip会将每个项目截断为最短列表的长度:
>>> zip(*[('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', )]) [('a', 'b', 'c', 'd', 'e')]
您可以使用没有函数的map来填充空结果,而不是:
>>> map(None, *[('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', )]) [('a', 'b', 'c', 'd', 'e'), (1, 2, 3, 4, None)]
zip()虽然略快.
我喜欢zip(*iterable)
在我的程序中使用(这是你正在寻找的代码段),如下所示:
def unzip(iterable): return zip(*iterable)
我发现unzip
更具可读性.
>>> original = [('a', 1), ('b', 2), ('c', 3), ('d', 4)] >>> tuple([list(tup) for tup in zip(*original)]) (['a', 'b', 'c', 'd'], [1, 2, 3, 4])
在问题中给出一个列表元组.
list1, list2 = [list(tup) for tup in zip(*original)]
解压缩两个列表.