Python 如何并行遍历两个列表?

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("

我有两个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("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))
    

  • 创建列表:探索了两种类型的列表创建方法:使用(a)
    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))
    

  • 理解这些结果: 程序员必须确定每个操作中有意义或有意义的计算时间

    例如,出于打印目的,如果此时间标准为1秒,即10**0秒,则在1秒时查看左侧图形的y轴,并将其水平投影,直到到达单项式曲线,我们会看到超过144个元素的列表大小将对pro产生巨大的计算成本和意义grammer。也就是说,对于较小的列表大小,本次调查中提到的方法所获得的任何性能对程序员来说都是微不足道的。程序员将得出结论,迭代打印语句的
    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具有的优势