我有一个序列列表,每个序列有两个项目。我想把它变成两个列表。
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'的方式吗?或者我应该坚持我拥有的东西?欢迎对编程风格进行任何更正或反馈,我是新手,并尝试学习最佳实践。
答案 0 :(得分: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()
内置函数组可以通过索引进行迭代,所以当你传递一堆两元素元组时,你得到一个两元素的元组列表,其中第一个元组包含每个元组的第一个元素来自catalog
,第二个元组包含来自catalog
的每个元组的第二个元素。
在快速计时测试中,当我使用1,000,000对测试时,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
答案 1 :(得分: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))