7

可能重复:
Python 中的转置/解压缩函数

我有一个序列列表,每个序列有两个项目。我想把它变成两个列表。

catalog = [('abc', '123'), ('foo', '456'), ('bar', '789'), ('test', '1337')]

现在我只是这样做:

names = []
vals = []

for product in catalog:
        names.append(product[0])
        vals.append(product[1])

print (names)
print (vals)

它输出两个列表,并且工作得很好:

['abc', 'foo', 'bar', 'test']
['123', '456', '789', '1337']

有没有一种更整洁、更“pythonic”的方式来做到这一点?还是我应该坚持我所拥有的?欢迎对编程风格进行任何更正或反馈,我是新手,正在努力学习最佳实践。

4

2 回答 2

14
>>> catalog = [('abc', '123'), ('foo', '456'), ('bar', '789'), ('test', '1337')]
>>> names, vals = zip(*catalog)
>>> names
('abc', 'foo', 'bar', 'test')
>>> vals
('123', '456', '789', '1337')

这里的*catalog语法称为Unpacking Argument Lists,并zip(*catalog)转换为调用zip(catalog[0], catalog[1], catalog[2], ...)

内置函数按索引对zip()可迭代对象进行分组,因此当您传递一堆如上所述的双元素元组时,您会得到一个双元素元组列表,其中第一个元组包含来自 的每个元组的第一个元素,catalog第二个元组包含来自每个元组的第二个元素catalog

在快速 timeit 测试中,zip()当我使用 1,000,000 对进行测试时,该版本的性能优于循环方法:

In [1]: catalog = [(i, i+1) for i in range(1000000)]

In [2]: def with_zip():
   ...:     return zip(*catalog)
   ...: 

In [3]: def without_zip():
   ...:     names, vals = [], []
   ...:     for name, val in catalog:
   ...:         names.append(name)
   ...:         vals.append(val)
   ...:     return names, vals
   ...: 

In [4]: %timeit with_zip()
1 loops, best of 3: 176 ms per loop

In [5]: %timeit without_zip()
1 loops, best of 3: 250 ms per loop
于 2012-12-17T18:51:38.577 回答
3

当然,使用这个:

lst = [('abc', '123'), ('foo', '456'), ('bar', '789'), ('test', '1337')]
tup1, tup2 = zip(*lst)

以上将返回一对带有元素的元组。如果您需要列表,请使用以下命令:

lst = [('abc', '123'), ('foo', '456'), ('bar', '789'), ('test', '1337')]
lst1, lst2 = map(list, zip(*lst))
于 2012-12-17T18:53:35.387 回答