2010-07-12 16 views
11

Diciamo che ho 2 elenchi in Python e voglio passare in rassegna ciascuno di essi in parallelo - ad es. fare qualcosa con elemento 1 per entrambi gli elenchi, fare qualcosa con l'elemento 2 per entrambi gli elenchi ... So che posso fare questo utilizzando un indice:C'è un modo per avere paralleli per ogni ciclo?

for listIndex in range(len(list1)): 
    doSomething(list1[listIndex]) 
    doSomething(list2[listIndex]) 

Ma c'è un modo per fare questo in modo più intuitivo, con un ciclo foreach? Qualcosa come for list1Value in list1, list2Value in list2 ...?

Attualmente mi sono imbattuto in questa situazione in Python, ma questa è una domanda di vecchia data e sarei interessato a sapere se è possibile farlo in qualsiasi lingua. (Ho appena dato per scontato che Python abbia più probabilità di avere un metodo per gestire questo.)

risposta

14

Qualcosa di simile?

for (a,b) in zip(list1, list2): 
    doSomething(a) 
    doSomething(b) 

Anche se doSomething() non sta facendo I/O o l'aggiornamento di stato globale, e funziona da solo su uno degli elementi alla volta, l'ordine non ha importanza così si potrebbe utilizzare chain() (da itertools):

for x in chain(list1, list2): 
    doSomething(x) 

proposito, from itertools import * è una cosa che faccio molto spesso. Si consideri izip() invece di utilizzare lo zip() che ho fornito sopra. Cerca anche in izip_longest(), izip(count(), lst), ecc. Benvenuti nella programmazione funzionale. :-)

Oh, e zippare funziona anche con più "colonne":

for idx, a, b, c in izip(count(), A, B, C): 
    ... 
+0

+1 per 'itertool.chain()'! – EOL

+0

un esempio di globalità e nessuna applicabilità di catena: 'per item1, item2 in zip (iter1, iter2): fileobj.write ("% s% s \ n "% (elemento1, elemento2))' – tzot

+0

grazie questo è ottimo ! solo una domanda veloce ... questo metodo richiede che le liste abbiano la stessa lunghezza? cosa succede se non lo sono? – froadie

4

che dipenderà dalla lingua. Pitone ha in realtà un metodo piuttosto semplice per questo:

a = (0,1,2,3,4,5,6,7,8,9) 
b = "ABCDEFGHIJ" 
for pair in zip(a,b): 
    print("%d => %s" % pair) 
4

Uso zip o itertools.izip per questo:

for item1, item2 in zip(iterable1, iterable2): 
    # process the items in parallel 

itertools.izip in pitone < 3 e zip in pitone ≥ 3 iteratori ritorno; cioè forniscono tuple di coppie (o terzine, quartetti ecc.) su richiesta. Python crea un elenco di tuple, quindi i requisiti di memoria potrebbero essere grandi se la più piccola delle sequenze è piuttosto lunga.

+0

zip sembra funzionare in Python 2.6 e – froadie

+0

@froadie: non ho mai detto che non funziona. – tzot

Problemi correlati