Obtenga la diferencia entre dos listas con entradas únicas

Resuelto Max Frai asked hace 14 años • 33 respuestas

Tengo dos listas en Python:

temp1 = ['One', 'Two', 'Three', 'Four']
temp2 = ['One', 'Two']

Suponiendo que los elementos de cada lista son únicos, quiero crear una tercera lista con elementos de la primera lista que no están en la segunda lista:

temp3 = ['Three', 'Four']

¿Existen formas rápidas sin ciclos ni comprobaciones?

Max Frai avatar Aug 12 '10 02:08 Max Frai
Aceptado

Para obtener elementos que están temp1pero no temp2 ( asumiendo la unicidad de los elementos en cada lista ):

In [5]: list(set(temp1) - set(temp2))
Out[5]: ['Four', 'Three']

Cuidado que es asimétrico:

In [5]: set([1, 2]) - set([2, 3])
Out[5]: set([1]) 

donde podría esperar/querer que sea igual set([1, 3]). Si quieres set([1, 3])como respuesta, puedes usar set([1, 2]).symmetric_difference(set([2, 3])).

ars avatar Aug 11 '2010 19:08 ars

Todas las soluciones existentes ofrecen uno u otro de:

  • Más rápido que el rendimiento O(n*m).
  • Preservar el orden de la lista de entrada.

Pero hasta ahora ninguna solución tiene ambas cosas. Si quieres ambos, prueba esto:

s = set(temp2)
temp3 = [x for x in temp1 if x not in s]

Prueba de rendimiento

import timeit
init = 'temp1 = list(range(100)); temp2 = [i * 2 for i in range(50)]'
print timeit.timeit('list(set(temp1) - set(temp2))', init, number = 100000)
print timeit.timeit('s = set(temp2);[x for x in temp1 if x not in s]', init, number = 100000)
print timeit.timeit('[item for item in temp1 if item not in temp2]', init, number = 100000)

Resultados:

4.34620224079 # ars' answer
4.2770634955  # This answer
30.7715615392 # matt b's answer

El método que presenté, además de preservar el orden, también es (ligeramente) más rápido que la resta de conjuntos porque no requiere la construcción de un conjunto innecesario. La diferencia de rendimiento sería más notable si la primera lista fuera considerablemente más larga que la segunda y si el hash fuera caro. Aquí hay una segunda prueba que demuestra esto:

init = '''
temp1 = [str(i) for i in range(100000)]
temp2 = [str(i * 2) for i in range(50)]
'''

Resultados:

11.3836875916 # ars' answer
3.63890368748 # this answer (3 times faster!)
37.7445402279 # matt b's answer
Mark Byers avatar Aug 11 '2010 19:08 Mark Byers

Se puede hacer usando el operador XOR de Python.

  • Esto eliminará los duplicados en cada lista.
  • Esto mostrará la diferencia entre temp1 y temp2 y temp2 y temp1.

set(temp1) ^ set(temp2)
SuperNova avatar Jul 07 '2016 07:07 SuperNova