2010-03-06 19 views
12

¿Cuál es la forma pitónica de iterar simultáneamente en dos listas?Python iteración doble

Supongamos que quiero comparar línea de dos archivos por línea (comparar cada línea de i º en un archivo con la línea i º del otro archivo), me gustaría hacer algo como esto:

file1 = csv.reader(open(filename1),...) 
file2 = csv.reader(open(filename2),...) 

for line1 in file1 and line2 in file2: #pseudo-code! 
    if line1 != line2: 
     print "files are not identical" 
     break 

¿Cuál es la forma pitónica de lograr esto?


Editar: No estoy usando un identificador de archivos, sino más bien un lector CSV (csv.reader(open(file),...)), y no parece zip() para trabajar con él ...


edición final : como @Alex M. sugirió, zip() carga los archivos en la memoria en la primera iteración, por lo que en archivos grandes se trata de un problema. En Python 2, usar itertools resuelve el problema.

+0

Posible duplicado de [¿Cómo puedo iterar a través de dos listas en paralelo en Python?] (Http://stackoverflow.com/questions/1663807/how-can-i-iterate-through-two-lists-in-parallel -in-python) –

Respuesta

13

En Python 2, debe importar itertools y utilizar su izip:

with open(file1) as f1: 
    with open(file2) as f2: 
    for line1, line2 in itertools.izip(f1, f2): 
     if line1 != line2: 
     print 'files are different' 
     break 

con la incorporada en el zip, ambos archivos se pueden leer en su totalidad en la memoria a la vez en el inicio del bucle, que puede no ser lo que quieres. En Python 3, el zip incorporado funciona como itertools.izip en Python 2 - incrementalmente.

+0

¡Esto hace el trabajo! De hecho, el problema era que los archivos eran bastante grandes y 'zip()' los cargaba todos en la memoria ... –

+0

Ah, tal vez por eso no veo ninguna diferencia. Estoy usando Python 3.1. – kennytm

+0

@KennyTM, sí, no "tal vez": en Python 3 muchas cosas que solían basarse en las listas de todas las memorias en Python 2 se han vuelto incrementales e iterativas. Por lo tanto, es importante aclarar siempre si las preguntas y respuestas se relacionan con Python 2 o Python 3: en Python 2 el (mejor ;-) enfoque incremental e iterativo es, por así decirlo, "opt-in" (debe obtenerlo explícitamente)), en Python 3 es intrínseco (debe llamar explícitamente a 'list' en los raros casos relativos en los que realmente ** desea ** una lista, todo en la memoria a la vez ;-). –

3

En lockstep (para Python ≥3):

for line1, line2 in zip(file1, file2): 
    # etc. 

Como un "array 2D":

for line1 in file1: 
    for line2 in file2: 
    # etc. 
    # you may need to rewind file2 to the beginning. 
+0

Gracias, estoy buscando el método Lockstep. ¿Alguna idea de por qué este método no funciona para un 'csv.reader()'? –

+0

tal vez debería aclarar que para la "matriz 2D" podría ser necesario reiniciar el iterador interno ... – fortran

+1

@Yuval, por favor edite su respuesta para mostrar exactamente cómo está tratando de usar zip con un (uno ?!) csv .reader - este comentario es totalmente misterioso. –

6

yo voto para el uso de zip. El manual sugiere "Para bucle sobre dos o más secuencias al mismo tiempo, las entradas se pueden combinar con la función zip()"

Por ejemplo,

list_one = ['nachos', 'sandwich', 'name'] 
list_two = ['nachos', 'sandwich', 'the game'] 
for one, two in zip(list_one, list_two): 
    if one != two: 
     print "Difference found"