¿Comparando dos listas y solo imprimiendo las diferencias? (XORING dos listas)

Estoy tratando de crear una función que toma en 2 listas y devuelve la lista que solo tiene las diferencias de las dos listas.

Ejemplo:

a = [1,2,5,7,9] b = [1,2,4,8,9] 

El resultado debe imprimir [4,5,7,8]

La función hasta ahora:

 def xor(list1, list2): list3=list1+list2 for i in range(0, len(list3)): x=list3[i] y=i while y>0 and x<list3[y-1]: list3[y]=list3[y-1] y=y-1 list3[y]=x last=list3[-1] for i in range(len(list3) -2, -1, -1): if last==list3[i]: del list3[i] else: last=list3[i] return list3 print xor([1,2,5,7,8],[1,2,4,8,9]) 

El primer bucle for lo ordena, el segundo elimina los duplicados. El problema es que el resultado es [1,2,4,5,7,8,9] no [4,5,7,8] , por lo que no elimina completamente los duplicados. ¿Qué puedo agregar para hacer esto? No puedo usar ningún módulo especial, .sort, set ni nada, solo bucles básicamente.

Básicamente, desea agregar un elemento a su nueva lista si está presente en una y no en otra. Aquí hay un bucle compacto que puede hacerlo. Para cada elemento en las dos listas (concatenarlas con list1+list2 ), agregamos el elemento si no está presente en una de ellas:

 [a for a in list1+list2 if (a not in list1) or (a not in list2)] 

Puede transformarlo fácilmente en un código más no piónico con un bucle explícito a través de elementos como lo ha hecho ahora, pero honestamente no veo un punto (no es que importe):

 def xor(list1, list2): outputlist = [] list3 = list1 + list2 for i in range(0, len(list3)): if ((list3[i] not in list1) or (list3[i] not in list2)) and (list3[i] not in outputlist): outputlist[len(outputlist):] = [list3[i]] return outputlist 

Usar set es mejor

 >>> a = [1,2,5,7,9] >>> b = [1,2,4,8,9] >>> set(a).symmetric_difference(b) {4, 5, 7, 8} 

Gracias a @DSM, una oración mejor es:

 >>> set(a)^set(b) 

Estas dos afirmaciones son las mismas. Pero este último es más claro.

Actualización: lo siento, no vi el último requisito: no puedo usar set. Por lo que veo, la solución provista por @sashkello es la mejor.

Nota: Esto es realmente unpythonic y solo se debe usar como una respuesta para la tarea 🙂

Una vez que haya ordenado ambas listas, puede encontrar duplicados haciendo lo siguiente:

1) Coloca los iteradores al inicio de A y B

2) Si Aitr es mayor que Bitr, avance Bitr después de colocar el valor de Bitr en la lista de devolución

3) De lo contrario, si Bitr es mayor que Aitr, avance Aiter después de colocar el valor de Aitr en la lista de devolución.

4) De lo contrario, ha encontrado un duplicado, avance Aitr y Bitr

Este código funciona suponiendo que tienes listas ordenadas. Funciona en tiempo lineal, en lugar de cuadrático como muchas de las otras soluciones dadas.

 def diff(sl0, sl1): i0, i1 = 0, 0 while i0 < len(sl0) and i1 < len(sl1): if sl0[i0] == sl1[i1]: i0 += 1 i1 += 1 elif sl0[i0] < sl1[i1]: yield sl0[i0] i0 += 1 else: yield sl1[i1] i1 += 1 for i in xrange(i0, len(sl0)): yield sl0[i] for i in xrange(i1, len(sl1)): yield sl1[i] print list(diff([1,2,5,7,9], [1,2,4,8,9])) 

Prueba esto,

  a = [1,2,5,7,9] b = [1,2,4,8,9] print set(a).symmetric_difference(set(b)) 

Simple, pero no particularmente eficiente 🙂

 >>> a = [1,2,5,7,9] >>> b = [1,2,4,8,9] >>> [i for i in a+b if (a+b).count(i)==1] [5, 7, 4, 8] 

O con “solo bucles”

 >>> res = [] >>> for i in a+b: ... c = 0 ... for j in a+b: ... if i==j: ... c += 1 ... if c == 1: ... res.append(i) ... >>> res [5, 7, 4, 8]