Python 如何并行遍历两个列表?
我有两个Python版本的iterables,我想两人一组讨论:Python 如何并行遍历两个列表?,python,list,for-loop,iterator,Python,List,For Loop,Iterator,我有两个Python版本的iterables,我想两人一组讨论: foo = (1, 2, 3) bar = (4, 5, 6) for (f, b) in some_iterator(foo, bar): print("f: ", f, "; b: ", b) 它应导致: f: 1; b: 4 f: 2; b: 5 f: 3; b: 6 一种方法是迭代索引: for i in range(len(foo)): print("
foo = (1, 2, 3)
bar = (4, 5, 6)
for (f, b) in some_iterator(foo, bar):
print("f: ", f, "; b: ", b)
它应导致:
f: 1; b: 4
f: 2; b: 5
f: 3; b: 6
一种方法是迭代索引:
for i in range(len(foo)):
print("f: ", foo[i], "; b: ", bar[i])
但这对我来说似乎有点不太和谐。有更好的方法吗?您需要
zip
功能
for (f,b) in zip(foo, bar):
print "f: ", f ,"; b: ", b
def iterate_multi(*lists):
for i in range(min(map(len,lists))):
yield tuple(l[i] for l in lists)
for l1, l2, l3 in iterate_multi([1,2,3],[4,5,6],[7,8,9]):
print(str(l1)+","+str(l2)+","+str(l3))
Python 3
zip
在foo
或bar
中较短者停止时停止
在Python 3中,
返回元组的迭代器,如Python2中的itertools.izip
。获取列表
对于元组,使用列表(zip(foo,bar))
。并压缩,直到两个迭代器都
筋疲力尽,你会用
Python 2
在Python 2中,
返回元组列表。当foo
和bar
不是很大的时候,这是很好的。如果它们都是巨大的,那么形成zip(foo,bar)
是一个不必要的巨大过程
临时变量,应替换为itertools.izip
或
itertools.izip_longest,返回迭代器而不是列表
import itertools
for f,b in itertools.izip(foo,bar):
print(f,b)
for f,b in itertools.izip_longest(foo,bar):
print(f,b)
izip
在foo
或bar
用尽时停止。
izip_longest
在foo
和bar
用尽时停止。
当较短的迭代器用尽时,izip_longest
将生成一个元组,其中None
位于该迭代器对应的位置。如果愿意,您还可以在None
之外设置不同的fillvalue
。请看这里以了解更多信息
还要注意的是
zip
及其类似zip
的brethen可以接受任意数量的iterables作为参数。比如说,
for num, cheese, color in zip([1,2,3], ['manchego', 'stilton', 'brie'],
['red', 'blue', 'green']):
print('{} {} {}'.format(num, color, cheese))
印刷品
1 red manchego
2 blue stilton
3 green brie
您应该使用“”函数。下面是您自己的zip函数的示例
def custom_zip(seq1, seq2):
it1 = iter(seq1)
it2 = iter(seq2)
while True:
yield next(it1), next(it2)
下面是如何使用列表理解来完成此操作:
a = (1, 2, 3)
b = (4, 5, 6)
[print('f:', i, '; b', j) for i, j in zip(a, b)]
印刷品:
f: 1 ; b 4
f: 2 ; b 5
f: 3 ; b 6
您可以使用comprehension将第n个元素绑定到一个元组或列表中,然后使用生成器函数将它们传递出去
for (f,b) in zip(foo, bar):
print "f: ", f ,"; b: ", b
def iterate_multi(*lists):
for i in range(min(map(len,lists))):
yield tuple(l[i] for l in lists)
for l1, l2, l3 in iterate_multi([1,2,3],[4,5,6],[7,8,9]):
print(str(l1)+","+str(l2)+","+str(l3))
在回答的基础上,我比较了使用Python 3.6的zip()
函数、Python的enumerate()
函数、使用手动计数器(请参见count()
函数)、使用索引列表以及在一个特殊场景中使用其中一个列表的元素时两个相同列表的迭代性能(可以使用foo
或bar
)为另一个列表编制索引。使用timeit()分别研究了它们打印和创建新列表的性能
函数,其中使用的重复次数为1000次。下面给出了我为执行这些调查而创建的Python脚本之一。foo
和bar
列表的大小从10到1000000个元素不等
结果:
zip()近似
函数,在将精度公差分解为+/-5%后。当列表大小小于100个元素时发生异常。在这种情况下,索引列表方法略慢于zip()
函数,而enumerate()函数
函数快了约9%。其他方法产生的性能与zip()
函数类似
for (f,b) in zip(foo, bar):
print "f: ", f ,"; b: ", b
def iterate_multi(*lists):
for i in range(min(map(len,lists))):
yield tuple(l[i] for l in lists)
for l1, l2, l3 in iterate_multi([1,2,3],[4,5,6],[7,8,9]):
print(str(l1)+","+str(l2)+","+str(l3))
list.append()
方法和(b)列表理解。在考虑+/-5%的精度公差后,对于这两种方法,zip()
函数的执行速度比enumerate()函数快,比使用列表索引快,比使用手动计数器快。zip()函数的性能提高
函数在这些比较中可以快5%到60%。有趣的是,使用foo
元素索引bar
可以产生与zip()函数相同或更快的性能(5%到20%)
for (f,b) in zip(foo, bar):
print "f: ", f ,"; b: ", b
def iterate_multi(*lists):
for i in range(min(map(len,lists))):
yield tuple(l[i] for l in lists)
for l1, l2, l3 in iterate_multi([1,2,3],[4,5,6],[7,8,9]):
print(str(l1)+","+str(l2)+","+str(l3))
zip()
函数的性能与其他方法类似
结论
在创建list
期间,使用zip()
函数并行迭代两个列表可以获得显著的性能。当并行迭代两个列表以打印出两个列表的元素时,zip()
函数将产生与enumerate()类似的性能
功能,如使用手动计数器变量,如使用索引列表,以及在特殊情况下,两个列表中的一个(或foo
或bar
)的元素可用于索引另一个列表
用于调查列表创建的Python3.6脚本。
Python 3:
import itertools as it
for foo, bar in list(it.izip_longest(list1, list2)):
print(foo, bar)
在Python3.0之前,如果有大量的元素,您可能希望使用
itertools.izip
。@unutbu为什么我更喜欢OP的方法而不是izip
方法(即使izip
/zip
看起来更干净)?您可能想先提到Python 3,因为它可能更能证明未来。此外,值得指出的是,在Python 3中,zip()具有只有itertools.iz具有的优势