¿Cómo recorrer dos listas en paralelo?

865

Tengo dos iterables en Python, y quiero revisarlos en pares:

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

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

Debería resultar en:

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

Una forma de hacerlo es iterar sobre los índices:

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

Pero eso me parece un tanto no propónico. Hay una mejor manera de hacerlo?

Nathan Fellman
fuente

Respuestas:

1354

Python 3

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

zipse detiene cuando el más corto fooo se bardetiene.

En Python 3 , zip devuelve un iterador de tuplas, como itertools.izipen Python2. Para obtener una lista de tuplas, use list(zip(foo, bar)). Y para comprimir hasta que se agoten ambos iteradores, usaría itertools.zip_longest .

Python 2

En Python 2 , zip devuelve una lista de tuplas. Esto está bien cuando fooy barno son masivos. Si ambos son masivos, la formación zip(foo,bar)es una variable temporal innecesariamente masiva y debe reemplazarse por itertools.izipo itertools.izip_longest, que devuelve un iterador en lugar de una lista.

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)

izipse detiene cuando fooo barestá agotado. izip_longestse detiene cuando ambos fooy barestán agotados. Cuando los iteradores más cortos están agotados, izip_longestproduce una tupla Noneen la posición correspondiente a ese iterador. También puede establecer una diferente fillvalueademás Nonesi lo desea. Vea aquí la historia completa .


Tenga en cuenta también que zipy su zipbreen-like puede aceptar un número arbitrario de iterables como argumentos. Por ejemplo,

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

huellas dactilares

1 red manchego
2 blue stilton
3 green brie
unutbu
fuente
@unutbu ¿Por qué preferiría el método de OP sobre el método izip(aunque el izip/ se zipve mucho más limpio)?
armundle
3
Es posible que desee mencionar Python 3 primero, ya que probablemente sea más a prueba de futuro. Además, vale la pena señalar que en Python 3, zip () tiene exactamente esa ventaja que solo itertools.izip () tenía en Python 2 y, por lo tanto, suele ser el camino a seguir.
Daniel S.
3
¿Puedo pedirle que actualice su respuesta a indicar expresamente que zipy zip-como funciones de itertoolsaceptar cualquier número de iterables y no sólo 2? Esta pregunta es canónica ahora y su respuesta es la única que vale la pena actualizar.
vaultah
¿Qué pasa si además quiero el índice i? ¿Puedo envolver ese zip en enumerate?
Charlie Parker
2
@CharlieParker: Sí, puedes, pero luego lo usarías for i, (f, b) in enumerate(zip(foo, bar)).
unutbu
60

Tú quieres la zipfunción.

for (f,b) in zip(foo, bar):
    print "f: ", f ,"; b: ", b
Karl Guertin
fuente
11
Antes de Python 3.0, querría usar itertools.izipsi tiene una gran cantidad de elementos.
Georg Schölly
15

Debe usar la función ' zip '. Aquí hay un ejemplo de cómo puede verse su propia función zip

def custom_zip(seq1, seq2):
    it1 = iter(seq1)
    it2 = iter(seq2)
    while True:
        yield next(it1), next(it2)
Vlad Bezden
fuente
¿No tiene esto exactamente el mismo resultado que zip(seq1, seq2)?
Niklas Mertsch
@NiklasMertsch sí, tiene exactamente el mismo resultado. Acabo de dar un ejemplo de cómo se ve la función zip
Vlad Bezden
1

Puede agrupar los enésimos elementos en una tupla o lista usando la comprensión, luego pasarlos con una función generadora.

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
fuente
-2

En caso de que alguien esté buscando algo como esto, lo encontré muy simple y fácil:

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

Las listas se iterarán con su contenido completo, a diferencia de zip (), que solo itera hasta la longitud mínima de contenido.

VladiC4T
fuente
los votantes negativos deben comentar lo que encontraron mal con mi enfoque o si no encaja como una posible solución para esta pregunta.
VladiC4T