2つのリストを並行して反復する方法は?


864

Pythonには2つのイテラブルがあり、それらをペアで調べたいと思います。

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

これを行う1つの方法は、インデックスを反復処理することです。

for i in xrange(len(foo)):
    print "f: ", foo[i], "; b: ", b[i]

しかし、それは私には幾分不器用に思えます。それを行うより良い方法はありますか?

回答:


1353

Python 3

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

zipfooまたはの短いときにbar停止します。

Pythonの3zip のように、タプルのイテレータを返しitertools.izipPython2です。タプルのリストを取得するには、を使用しますlist(zip(foo, bar))。そして、両方のイテレーターが使い果たされるまで圧縮するには、itertools.zip_longestを使用し ます

Python 2

ではPythonの2zip タプルのリストを返します。これは時に問題ありfoobar大規模ではありません。それらが両方とも大規模である場合、フォーミングzip(foo,bar)は不必要に大規模な一時変数であり、itertools.izipor 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)

izipfooまたはいずれかbarがなくなると停止します。 izip_longest両方が停止するfoobar使い果たされます。短い反復子が使い果たされると、その反復子に対応する位置にizip_longestタプルが生成Noneされます。必要に応じてfillvalue、他にも別のものを設定できNoneます。ここを参照してください完全な物語


またzip、そのzipようなbrethenは任意の数のイテラブルを引数として受け入れることができることにも注意してください。例えば、

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 izipizip/の方zipがずっときれいに見えますが)なぜOPよりもOPの方が好きですか?
armundle 2016年

3
Python 3の方が先に進む可能性が高いため、最初にPython 3について言及することをお勧めします。さらに、Python 3ではzip()には、Python 2ではitertools.izip()だけが持っていたのとまったく同じ利点があるため、通常はそれが適切な方法であることを指摘しておく価値があります。
ダニエルS.

3
私は明示的にその状態にあなたの答えを更新するために求めることができるzipzipの様な機能itertoolsだけ2をイテレート可能オブジェクトの任意の数を受け入れ、ありませんか?この質問は今では標準的であり、あなたの答えは更新する価値がある唯一のものです。
2016

さらにインデックスが必要な場合はどうなりますiか?そのzipを列挙でラップできますか?
チャーリーパーカー

2
@CharlieParker:はい、できますが、使用しますfor i, (f, b) in enumerate(zip(foo, bar))
unutbu 2018年


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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.