Digamos que tengo dos listas, l1
y l2
. Quiero realizar l1 - l2
, que devuelve todos los elementos de l1
no en l2
.
Puedo pensar en un enfoque de bucle ingenuo para hacer esto, pero eso será realmente ineficiente. ¿Cuál es una forma pitónica y eficiente de hacer esto?
Como ejemplo, si tengo l1 = [1,2,6,8] and l2 = [2,3,5,8]
, l1 - l2
debería volver[1,6]
Respuestas:
Python tiene una función de lenguaje llamada List Comprehensions que se adapta perfectamente para hacer que este tipo de cosas sea extremadamente fácil. La siguiente declaración hace exactamente lo que desea y almacena el resultado en
l3
:l3
contendrá[1, 6]
.fuente
in
operador no es tan eficiente en una lista.in
en una lista está O (n), mientras quein
en un conjunto está O (1). Sin embargo, hasta que llegue a miles de elementos o más, es poco probable que note la diferencia.l3 = [x for x in l1 if x not in set(l2)]
? Estoy seguro deset(l2)
que se llamaría más de una vez.l2s = set(l2)
y luego decirl3 = [x for x in l1 if x not in l2s]
. Ligeramente más fácil.Una forma es usar conjuntos:
fuente
l1
, lo que puede ser un efecto secundario no deseado.timeit.timeit('a = [1,2,3,4]; b = [1,3]; c = [i for i in a if a not in b]', number=100000) -> 0.12061533199999985
timeit.timeit('a = {1,2,3,4}; b = {1,3}; c = a - b', number=100000) -> 0.04106225999998969
. Entonces, si el rendimiento es un factor significativo, esta respuesta puede ser más apropiada (y también si no le importan los duplicados o el orden)Como alternativa, también puede usar
filter
con la expresión lambda para obtener el resultado deseado. Por ejemplo:Comparación de rendimiento
Aquí estoy comparando el rendimiento de todas las respuestas mencionadas aquí. Como se esperaba, la
set
operación basada en Arkku es más rápida.Diferencia establecida de Arkku - Primero (0.124 usec por ciclo)
Lista Comprensión de Daniel Pryden con
set
búsqueda - Segundo (0.302 usec por ciclo)Lista de donas Comprensión en lista simple - Tercero (0.552 usec por ciclo)
Moinuddin Quadri's usando
filter
- Cuarto (0.972 usec por ciclo)Akshay Hazari está usando la combinación de
reduce
+filter
- Quinto (3.97 usec por ciclo)PD:
set
no mantiene el orden y elimina los elementos duplicados de la lista. Por lo tanto, no use la diferencia establecida si necesita alguno de estos.fuente
Ampliando la respuesta de Donut y las otras respuestas aquí, puede obtener mejores resultados utilizando una comprensión de generador en lugar de una comprensión de lista, y utilizando una
set
estructura de datos (ya que elin
operador es O (n) en una lista pero O (1) en un set).Así que aquí hay una función que funcionaría para usted:
El resultado será un iterable que va a buscar perezosamente la lista filtrada. Si necesita un objeto de lista real (por ejemplo, si necesita hacer un a
len()
en el resultado), puede crear fácilmente una lista como esta:fuente
Use el tipo de conjunto Python. Eso sería lo más pitónico. :)
Además, como es nativo, también debería ser el método más optimizado.
Ver:
http://docs.python.org/library/stdtypes.html#set
http://docs.python.org/library/sets.htm (para python anterior)
fuente
l1
incluye elementos repetidos.use Set Comprehensions {x para x en l2} o set (l2) para configurar, luego use List Comprehensions para obtener la lista
código de prueba de referencia:
resultado de la prueba de referencia:
fuente
l2set = set( l2 )
en lugar del2set = { x for x in l2 }
Solución alternativa
fuente