我有一个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])
有没有内置函数可以做到这一点?
我有一个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])
有没有内置函数可以做到这一点?
当前回答
下面是一个简单的单行回答,可以产生所需的输出:
original = [('a', 1), ('b', 2), ('c', 3), ('d', 4)]
list(zip(*original))
# [('a', 'b', 'c', 'd'), (1, 2, 3, 4)]
其他回答
你也可以
result = ([ a for a,b in original ], [ b for a,b in original ])
它的可伸缩性应该更好。特别是如果Python不扩展列表推导式,除非需要的话。
(顺便说一句,它生成一个二元组(对)列表,而不是像zip那样生成一个元组列表。)
如果生成器代替实际的列表是可以的,这将做到:
result = (( a for a,b in original ), ( b for a,b in original ))
在您请求每个元素之前,生成器不会仔细检查列表,但另一方面,它们会保留对原始列表的引用。
如果您的列表长度不相同,您可能不希望按照patrick的回答使用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没有函数来填充空结果为None:
>>> map(None, *[('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', )])
[('a', 'b', 'c', 'd', 'e'), (1, 2, 3, 4, None)]
不过Zip()稍微快一点。
要获得一个列表的元组,如问题中所示:
>>> 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)]
总结一下:
# data
a = ('a', 'b', 'c', 'd')
b = (1, 2, 3, 4)
# forward
zipped = zip(a, b) # [('a', 1), ('b', 2), ('c', 3), ('d', 4)]
# reverse
a_, b_ = zip(*zipped)
# verify
assert a == a_
assert b == b_
下面是一个简单的单行回答,可以产生所需的输出:
original = [('a', 1), ('b', 2), ('c', 3), ('d', 4)]
list(zip(*original))
# [('a', 'b', 'c', 'd'), (1, 2, 3, 4)]