2012-12-17 99 views
3

可能重复:
A Transpose/Unzip Function in 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'] 

有一个整齐的,更 'Python化' 方式这样做?还是应该坚持我拥有的?对编程风格的任何更正或反馈是值得欢迎的,我是新手,并试图学习最佳实践。

回答

10
>>> 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()内置功能组iterables的指数,所以当你通过一帮两个元素的元组如上,你会得到一个元组的两个元素的列表,其中第一个元组包含每个元组的第一个元素从catalog,而第二个元组包含来自catalog的每个元组的第二个元素。

在快速timeit测试zip()版本胜过一个循环的方式,当我和百万对测试:

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 
+0

这是完美的,谢谢!我从来没有听说过这个功能。我将链接到此功能的文档,供将来的读者阅读。 http://docs.python.org/3.3/library/functions.html#zip –

+1

它简洁而简单,但它的性能如何?在任何其他语言中创建一个十亿个参数将是可怕的。 –

+0

@MarkRansom - 我偶尔也想过这个...... – mgilson

2

当然,使用此:

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

一个元组对于我的使用来说可以做得很好,但是谢谢你彻底! –