Bagaimana cara mengulangi dua daftar secara paralel?

865

Saya memiliki dua iterables dengan Python, dan saya ingin membahasnya secara berpasangan:

foo = (1, 2, 3)
bar = (4, 5, 6)

for (f, b) in some_iterator(foo, bar):
    print "f: ", f, "; b: ", b

Itu harus menghasilkan:

f: 1; b: 4
f: 2; b: 5
f: 3; b: 6

Salah satu cara untuk melakukannya adalah beralih ke indeks:

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

Tetapi bagi saya itu agak unpythonic. Apakah ada cara yang lebih baik untuk melakukannya?

Nathan Fellman
sumber

Jawaban:

1354

Python 3

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

zipberhenti ketika lebih pendek fooatau barberhenti.

Dalam Python 3 , zip mengembalikan iterator tupel, seperti itertools.izippada Python2. Untuk mendapatkan daftar tupel, gunakan list(zip(foo, bar)). Dan untuk zip sampai kedua iterator habis, Anda akan menggunakan itertools.zip_longest .

Python 2

Dalam Python 2 , zip mengembalikan daftar tupel. Ini bagus saat foodan bartidak masif. Jika keduanya masif maka pembentukan zip(foo,bar)adalah variabel sementara masif yang tidak perlu, dan harus diganti oleh itertools.izipatau itertools.izip_longest, yang mengembalikan iterator dan bukan daftar.

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)

izipberhenti ketika salah satu fooatau barhabis. izip_longestberhenti ketika keduanya foodan barkelelahan. Ketika iterator yang lebih pendek habis, izip_longesthasilkan tuple dengan Noneposisi yang sesuai dengan iterator itu. Anda juga dapat mengatur fillvalueselain selain Nonejika Anda inginkan. Lihat di sini untuk cerita selengkapnya .


Perhatikan juga bahwa zipdan saudara- zipsaudaranya yang seperti itu dapat menerima jumlah yang dapat diubah dari iterables sebagai argumen. Sebagai contoh,

for num, cheese, color in zip([1,2,3], ['manchego', 'stilton', 'brie'], 
                              ['red', 'blue', 'green']):
    print('{} {} {}'.format(num, color, cheese))

cetakan

1 red manchego
2 blue stilton
3 green brie
unutbu
sumber
@unutbu Mengapa saya lebih suka metode OP daripada yang izip(meskipun izip/ zipterlihat jauh lebih bersih)?
armundle
3
Anda mungkin ingin menyebutkan Python 3 terlebih dahulu, karena mungkin lebih tahan di masa depan. Selain itu, ada baiknya * menunjukkan bahwa dalam Python 3, zip () memiliki keunggulan persis seperti yang dimiliki itertools.izip () di Python 2 dan dengan demikian biasanya cara untuk melakukannya.
Daniel S.
3
Bolehkah saya meminta Anda untuk memperbarui jawaban Anda untuk secara eksplisit menyatakan bahwa zipdan zip-seperti fungsi dari itertoolsmenerima sejumlah iterables dan bukan hanya 2? Pertanyaan ini kanonik sekarang dan jawaban Anda adalah satu-satunya yang layak diperbarui.
vaultah
bagaimana jika saya juga menginginkan indeks i? Bisakah saya membungkus zip itu dalam penghitungan?
Charlie Parker
2
@CharlieParker: Ya, Anda bisa, tetapi kemudian Anda akan menggunakannya for i, (f, b) in enumerate(zip(foo, bar)).
unutbu
60

Anda menginginkan zipfungsinya.

for (f,b) in zip(foo, bar):
    print "f: ", f ,"; b: ", b
Karl Guertin
sumber
11
Sebelum Python 3.0 Anda ingin menggunakan itertools.izipjika Anda memiliki banyak elemen.
Georg Schölly
15

Anda harus menggunakan fungsi ' zip '. Berikut adalah contoh bagaimana fungsi zip Anda sendiri dapat terlihat

def custom_zip(seq1, seq2):
    it1 = iter(seq1)
    it2 = iter(seq2)
    while True:
        yield next(it1), next(it2)
Vlad Bezden
sumber
Bukankah ini memiliki hasil yang persis sama zip(seq1, seq2)?
Niklas Mertsch
@NiklasMertsch ya hasilnya persis sama. Saya baru saja memberikan contoh bagaimana fungsi zip terlihat
Vlad Bezden
0

Anda dapat menggabungkan elemen-elemen ke dalam tuple atau daftar menggunakan pemahaman, lalu membagikannya dengan fungsi generator.

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))
Don F
sumber
-2

Jika seseorang mencari sesuatu seperti ini, saya merasa sangat sederhana dan mudah:

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

Daftar akan diiterasi dengan konten lengkapnya, tidak seperti zip () yang hanya diiterasi hingga panjang konten minimum.

VladiC4T
sumber
downvoters harus mengomentari apa yang mereka temukan salah dengan pendekatan saya atau jika tidak cocok sebagai solusi yang mungkin untuk pertanyaan ini.
VladiC4T