2011-08-19 23 views
8

tengo dos listas, por ejemplo x = [1,2,3,4,4,5,6,7,7] y = [3,4,5,6,7,8,9,10], quiero iterar sobre las dos listas al comparar elementos. Para aquellos que coinciden, me gustaría llamar a alguna función y eliminarla de las listas, en este ejemplo debería terminar con x = [1,2] e y = [8,9,10]. Los conjuntos no funcionarán para este problema debido a mi tipo de datos y al operador de comparación.python iterar sobre las dos listas al comparar elementos

for i in x: 
    for j in y: 
    if i ==j: 
     callsomefunction(i,j) 
     remove i, j from x and y respectively 
+0

Sus ejemplos están ordenados. ¿Sus datos reales están ordenados? –

+0

mis datos no se almacenan .. – user739807

+2

¿Los datos son ordenables? ¿Por qué tus datos no son manejables? ¿Qué tan grandes son 'x' y' y'? –

Respuesta

4

Editar: Después de descubrir la persona que hace la pregunta simplemente no sabía nada de __hash__ he proporcionado esta información en un comentario:

Para utilizar conjuntos, implementar __hash__. Por lo tanto, si obj1 == obj2 cuando obj1.a == obj2.a and ob1.b == obj2.b, __hash__ debe ser return hash((self.a, self.b)) y sus conjuntos funcionarán como se esperaba.

Eso resolvió su problema, y ​​cambiaron a usar conjuntos.

El resto de esta respuesta ahora es obsoleta, pero sigue siendo correcta (pero terriblemente ineficaz) así que lo dejo aquí.


Este código hace lo que quiere. Al final, newx y newy son los elementos que no se solapan de x y y específicamente.

x = [1,2,3,4,4,5,6,7,7] 
y = [3,4,5,6,7,8,9,10] 
# you can leave out bad and just compare against 
# x at the end if memory is more important than speed 
newx, bad, newy = [], [], [] 
for i in x: 
    if i in y: 
     callsomefunction(i) 
     bad.append(i) 
    else: 
     newx.append(i) 

for i in y: 
    if i not in bad: 
     newy.append(i) 

print newx 
print newy 

Sin embargo, sé sin siquiera ver su código que esta es la manera incorrecta de hacer esto. Ciertamente puedes hacerlo con sets, pero si no quieres hacerlo, eso depende de ti.

+0

El problema con los conjuntos es mis conjuntos de datos (objetos) por lo que la operación de comparación se define para comparar atributos específicos de los objetos. Déjame trabajar con esta solución. Gracias – user739807

+1

@ user739807, ¿Quieres decir "Definí' __cmp__' pero no '__hash__'"? Si es así, es posible que desee definir '__hash__'. Eso podría convertir este código cuadrático en código lineal. (Además, si está definiendo '__cmp__', probablemente quiera definir' __eq__' en su lugar.) –

+0

¡Gracias, _hash_ resuelve el problema! – user739807

1

Prueba esto:

for i in x: 
    if i in y: 
     callsomefunction(i) 
     x.remove(i) 
     y.remove(i) 

EDIT: respuesta actualizada

+0

zip no funcionará porque la longitud de ambas listas no es la misma. y nosotros también tenemos duplicados – user739807

+1

¿Ejecutaste este código? Esto no produce la salida solicitada por OP. –

+0

'zip()' produce resultados diferentes para el ciclo anidado utilizado por OP. 'itertools.product()' sería más adecuado, si no fuera por los requisitos 'remove (..)'. –

-1

¿qué tal esto:

import itertools 
x = [1,2,3,4,4,5,6,7,7] 
y = [3,4,5,6,7,8,9,10] 
output = map(somefunction, itertools.product(x,y)) 
+0

'itertools.product()' da el orden de iteración correcto, pero las cosas pueden ponerse feas una vez que comienzas a eliminar entradas de la lista mientras iteras. –

3

Ok, descartar mi post, que no había visto el punto donde mencionaste que los conjuntos no funcionarían.

Sin embargo, si está de acuerdo con un poco de trabajo, es posible que desee utilizar clases para que los operadores funcionen como se espera que lo hagan.

Creo que la forma más "pitonística" de hacer esto es usar conjuntos. A continuación, podría hacer:

x = set([1,2,3,4,4,5,6,7,7]) 
y = set([3,4,5,6,7,8,9,10]) 
for item in x.intersection(y): #y.intersection(x) is fine too. 
    my_function(item) #You could use my_function(item, item) if that's what your function requires 
    x.remove(item) 
    y.remove(item) 

creo que los conjuntos también son más eficientes que las listas de este tipo de trabajo cuando se trata de rendimiento (aunque esto podría no ser su máxima prioridad).

En una nota, también se puede utilizar:

x,y = x.difference(y), y.difference(x) 

Esto elimina de forma efectiva los elementos que se encuentran en X e Y de x e y.

+0

Ahora usa juegos, pero resultó que no sabía nada de '__hash__', por lo que pensó que no funcionaría para sus objetos. – agf

+0

¡Bueno, eso está todo bien! –

Cuestiones relacionadas