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


861

我在Python中有两个可迭代的对象,我想成对地遍历它们:

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 xrange(len(foo)):
    print "f: ", foo[i], "; b: ", b[i]

但这对我来说似乎有些不可思议。有更好的方法吗?

Answers:


1348

Python 3

for f, b in zip(foo, bar):
    print(f, b)

zipfoo或中的较短者bar停止。

Python 3zip 中,像itertools.izip在Python2中一样,返回元组的迭代器。要获取元组列表,请使用list(zip(foo, bar))。要压缩直到两个迭代器都用尽,可以使用 itertools.zip_longest

Python 2

Python 2中zip 返回一个元组列表。当foobar不是很大时,这很好。如果它们都是大量的,则形成zip(foo,bar)是不必要的大量临时变量,应将其替换为itertools.izipitertools.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)

izipfoobar耗尽时停止。 izip_longest当两个停止foobar耗尽。当较短的迭代器用尽时,将izip_longest生成一个元组,None其位置与该迭代器相对应。您还可以设置不同fillvalue之外None,如果你想。看到这里的完整故事


还要注意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

@unutbu为什么我会更喜欢OP的方法izip(即使izip/ zip看起来更干净)?
armundle

3
您可能想首先提到Python 3,因为它可能更适合未来。此外,值得指出的是,在Python 3中,zip()具有仅itertools.izip()在Python 2中才具有的优势,因此通常是这样。
Daniel S.

3
我是否可以要求您更新答案,以明确声明zipzip类似函数可以itertools接受任意数量的可迭代对象,而不仅仅是2个?这个问题现在是规范的,您的答案是唯一值得更新的问题。
vaultah '16

如果我还想要索引i怎么办?我可以将这个拉链包裹起来吗?
查理·帕克

2
@CharlieParker:是的,可以,但是您可以使用for i, (f, b) in enumerate(zip(foo, bar))
unutbu


15

您应该使用“ zip ”功能。这是您自己的zip函数的外观示例

def custom_zip(seq1, seq2):
    it1 = iter(seq1)
    it2 = iter(seq2)
    while True:
        yield next(it1), next(it2)

这样的结果不完全相同zip(seq1, seq2)吗?
Niklas Mertsch

@NiklasMertsch是的,它具有完全相同的结果。我只是提供了zip函数外观的示例
Vlad Bezden

0

您可以使用理解将第n个元素捆绑到一个元组或列表中,然后使用生成器函数将其传递出去。

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

-2

万一有人在寻找这样的东西,我发现它非常简单:

list_1 = ["Hello", "World"]
list_2 = [1, 2, 3]

for a,b in [(list_1, list_2)]:
    for element_a in a:
        ...
    for element_b in b:
        ...

>> Hello
World
1
2
3

列表将以其全部内容进行迭代,而zip()只会迭代最大内容长度。


投票者应就他们认为我的方法存在问题或如果它不适合解决此问题的方式发表评论。
VladiC4T

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.