2009-11-02 3 views
478

Ich habe zwei Iterables in Python, und ich will über sie paarweise gehen:Wie durchläuft man zwei Listen parallel?

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

Ein Weg, es zu tun, über die iteriert ist:

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

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

Es in Folge sollte Indizes:

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

Aber das scheint mir etwas unpythonisch. Gibt es einen besseren Weg, es zu tun?

Antwort

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

zip stoppt, wenn die kürzere foo oder bar stoppt.

In Python 2, zip gibt eine Liste von Tupeln. Dies ist in Ordnung, wenn foo und bar nicht massiv sind. Wenn sie beide massiv sind dann zip(foo,bar) ist eine unnötig massive temporäre Variable, und sollte durch itertools.izip oder itertools.izip_longest ersetzt werden, die einen Iterator anstelle einer Liste zurückgibt.

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 stoppt, wenn entweder foobar oder erschöpft ist. izip_longest stoppt, wenn sowohl foo als auch bar erschöpft sind. Wenn die kürzeren Iteratoren erschöpft sind, ergibt izip_longest ein Tupel mit None in der Position, die diesem Iterator entspricht. Sie können auch einen anderen fillvalue neben None setzen, wenn Sie möchten. Siehe hier für die full story.

In Python 3, zip gibt einen Iterator von Tupeln, wie in itertools.izip Python2. Um eine Liste von Tupeln zu erhalten, verwenden Sie list(zip(foo, bar)). Und um zu zippen, bis beide Iteratoren erschöpft sind, würden Sie itertools.zip_longest verwenden.


Beachten Sie auch, dass zip und seine zip -ähnlichen brethen kann eine beliebige Anzahl von Iterables als Argumente akzeptieren.Zum Beispiel

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

druckt

1 red manchego 
2 blue stilton 
3 green brie 
+3

@unutbu In Python 3 lautet der Funktionsname 'itertools.zip_longest' anstelle von' itertools.izip_longest' (im Prinzip 'zip ...' anstelle von 'izip ...' im 'itertools' Modul). Es ist eine Ein-Zeichen-Bearbeitung, sonst würde ich die super-kleine Korrektur selbst in deine Antwort schreiben. –

+1

@MichaelA: Danke für die Korrektur. – unutbu

+0

@unutbu Warum sollte ich die Methode von OP gegenüber der izip bevorzugen (obwohl die 'izip /' zip' viel sauberer aussieht)? – armundle

33

Sie wollen die zip Funktion.

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

Vor Python 3.0 würden Sie wollen 'itertools.izip' verwenden, wenn Sie eine große Anzahl von Elementen haben. –

9

Was Sie suchen, heißt zip.

11

Der eingebaute zip macht genau das, was Sie wollen. Wenn Sie das gleiche über iterables anstelle von Listen möchten, können Sie itertools.izip betrachten, das dasselbe tut, aber Ergebnisse nacheinander liefert.

2

Zip-Funktion löst das Problem
Docs: ZIP Library function

AIM: Um die Ausgabe nebeneinander Problem gestellt:

#value1 is a list 
value1 = driver.find_elements_by_class_name("review-text") 
#value2 is a list 
value2 = driver.find_elements_by_class_name("review-date") 

for val1 in value1: 
    print(val1.text) 
    print "\n" 
for val2 in value2: 
    print(val2.text) 
    print "\n" 

Ausgang:
review1
review2
Review3
date1
date2
date3

Lösung:

for val1, val2 in zip(value1,value2): 
    print (val1.text+':'+val2.text) 
    print "\n" 

Ausgang:
review1: date1
review2: date2
review3: date3

4

Sie sollten die Funktion 'zip' verwenden. Hier ist ein Beispiel, wie Sie Ihre eigene Zip-Funktion wie

aussehen kann
def custom_zip(seq1, seq2): 
    it1 = iter(seq1) 
    it2 = iter(seq2) 
    while True: 
     yield next(it1), next(it2) 
-1
def ncustom_zip(seq1,seq2,max_length): 
     length= len(seq1) if len(seq1)>len(seq2) else len(seq2) if max_length else len(seq1) if len(seq1)<len(seq2) else len(seq2) 
     for i in range(length): 
       x= seq1[i] if len(seq1)>i else None 
       y= seq2[i] if len(seq2)>i else None 
       yield x,y 


l=[12,2,3,9] 
p=[89,8,92,5,7] 

for i,j in ncustom_zip(l,p,True): 
     print i,j 
for i,j in ncustom_zip(l,p,False): 
     print i,j 
+1

Möchten Sie helfen, das Missverständnis zu bekämpfen, dass StackOveflow ein kostenloser Codierungsdienst ist? Dann erweitern Sie bitte Ihre Code-only-Antwort mit einer Erklärung. – Yunnosch

+0

ist das meine Antwort richtig? –

+0

Was ist falsch in meiner Antwort? –