Paralel olarak iki liste arasında nasıl yineleme yapılır?


862

Python'da iki tekrarlanabilirim var ve bunları çiftler halinde ele almak istiyorum:

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

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

Sonuç olarak:

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

Bunu yapmanın bir yolu, endeksleri yinelemektir:

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

Ama bu benim için bir şekilde kuralsız görünüyor. Bunu yapmanın daha iyi bir yolu var mı?

Yanıtlar:


1351

Python 3

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

zipkısaldığında durur fooveya bardurur.

In Python 3 , zip gibi dizilerini bir yineleyici döndürür itertools.izipPython2 içinde. Bir tuples listesi almak için tuşunu kullanın list(zip(foo, bar)). Her iki yineleyici de bitene kadar zip yapmak için itertools.zip_longest komutunu kullanabilirsiniz .

Python 2

In Python 2 , zip dizilerini bir listesini döndürür. Büyük olduğunda foove bariyi olmadığında bu iyidir . Her ikisi de büyükse, biçimlendirme zip(foo,bar)gereksiz yere büyük bir geçici değişkendir ve yerine bir liste yerine bir yineleyici döndüren itertools.izipveya ile değiştirilmelidir 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)

izipya fooda barbittiğinde durur . izip_longesther ikisi de durur foove bitince bar. Daha kısa yineleyiciler tükendiğinde, bu yineleyiciye karşılık gelen konumda izip_longestbir tuple verir None. Ayrıca farklı bir ayarlayabilirsiniz fillvalueyanında Nonedilerseniz. Hikayenin tamamı için buraya bakın .


Ayrıca zipve zipbenzeri kardeşin isteğe bağlı olarak yinelenebilir sayıda argüman olarak kabul edebileceğini unutmayın. Örneğin,

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

baskılar

1 red manchego
2 blue stilton
3 green brie

@unutbu Neden OP'nin yöntemini izip( izip/ zipçok daha temiz görünse bile) tercih etmeliyim ?
armundle

3
Öncelikle Python 3'ten bahsetmek isteyebilirsiniz, çünkü muhtemelen geleceğe daha dayanıklıdır. Dahası, Python 3'te zip () 'nin Python 2'de sadece itertools.izip ()' nin tam olarak bu avantajı olduğunu ve bu nedenle genellikle gitmenin yolu olduğunu belirtmek gerekir.
Daniel S.

3
Sizden zipve zipbenzeri işlevlerin itertoolsyalnızca 2 değil, tekrarlanabilir sayıları kabul ettiğini açıkça belirtmek için yanıtınızı güncellemenizi isteyebilir miyim ? Bu soru artık standarttır ve cevabınız güncellenmeye değer tek sorudur.
vaultah

ek olarak endeksi istiyorum i? Bu fermuarı numaralandırılmış olarak sarabilir miyim?
Charlie Parker

2
@CharlieParker: Evet yapabilirsin, ama sonra kullanırdın for i, (f, b) in enumerate(zip(foo, bar)).
unutbu

60

zipİşlevi istiyorsunuz .

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

11
Python 3.0'dan önce itertools.izip, çok sayıda öğeniz varsa kullanmak istersiniz .
Georg Schölly

15

' Zip ' işlevini kullanmalısınız . İşte kendi zip işlevinizin nasıl görünebileceğine dair bir örnek

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

Bunun sonucu tam olarak aynı değil zip(seq1, seq2)mi?
Niklas Mertsch

@NiklasMertsch evet, tam olarak aynı sonuca sahip. Zip fonksiyonunun nasıl göründüğüne sadece örnek verdim
Vlad Bezden

0

N. Öğeleri kavrayışı kullanarak bir demet ya da liste halinde paketleyebilir ve ardından bir jeneratör işlevi ile dışarı verebilirsiniz.

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

Birisi böyle bir şey arıyorsa, çok basit ve kolay buldum:

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

Listeler, yalnızca minimum içerik uzunluğuna kadar yinelenen zip () 'den farklı olarak tam içeriğiyle yinelenecektir.


downvoters benim yaklaşım ile neyi yanlış bulduklarını veya bu soru için olası bir çözüm olarak uymuyorsa yorum yapmalıdır.
VladiC4T

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.