我有一个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])

有没有内置函数可以做到这一点?


当前回答

这只是另一种方法,但它对我帮助很大,所以我写在这里:

具有这种数据结构的:

X=[1,2,3,4]
Y=['a','b','c','d']
XY=zip(X,Y)

导致:

In: XY
Out: [(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd')]

在我看来,更python化的解压方法是这样的:

x,y=zip(*XY)

但是这个返回一个元组,所以如果你需要一个列表,你可以使用:

x,y=(list(x),list(y))

其他回答

这只是另一种方法,但它对我帮助很大,所以我写在这里:

具有这种数据结构的:

X=[1,2,3,4]
Y=['a','b','c','d']
XY=zip(X,Y)

导致:

In: XY
Out: [(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd')]

在我看来,更python化的解压方法是这样的:

x,y=zip(*XY)

但是这个返回一个元组,所以如果你需要一个列表,你可以使用:

x,y=(list(x),list(y))

在2。X, 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(在被转换为元组之后),所以没有必要担心参数的数量变得太大。

在3。X, zip返回一个惰性迭代器,但这是简单的转换:

>>> list(zip(*[('a', 1), ('b', 2), ('c', 3), ('d', 4)]))
[('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)]

要获得一个列表的元组,如问题中所示:

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

你也可以

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

在您请求每个元素之前,生成器不会仔细检查列表,但另一方面,它们会保留对原始列表的引用。