Necesito comparar dos listas para crear una nueva lista de elementos específicos que se encuentran en una lista pero no en la otra. Por ejemplo:
main_list=[]
list_1=["a", "b", "c", "d", "e"]
list_2=["a", "f", "c", "m"]
Quiero recorrer list_1 y agregar a main_list todos los elementos de list_2 que no se encuentran en list_1.
El resultado debería ser:
main_list=["f", "m"]
¿Cómo puedo hacerlo con Python?

list_2que no aparecen en ninguna partelist_1o elementoslist_2que no están presentes en el mismo índicelist_1?Respuestas:
TL; DR:
SOLUCIÓN (1)
SOLUCIÓN (2) Quiere una lista ordenada
EXPLICACIONES:
(1) Se puede utilizar NumPy de
setdiff1d(array1,array2,assume_unique=False).assume_uniquepregunta al usuario si las matrices YA SON ÚNICAS.Si
False, entonces los elementos únicos se determinan primero.Si
True, la función asumirá que los elementos ya son únicos Y la función omitirá la determinación de los elementos únicos.Esto produce los valores únicos en
array1que no están enarray2.assume_uniqueesFalsepor defectoSi le preocupan los elementos únicos (basados en la respuesta de Chinny84 ), simplemente use (where
assume_unique=False=> el valor predeterminado):(2) Para aquellos que desean ordenar las respuestas, he creado una función personalizada:
Para obtener la respuesta, ejecute:
NOTAS LATERALES:
(a) La solución 2 (función personalizada
setdiff_sorted) devuelve una lista (en comparación con una matriz en la solución 1).(b) Si no está seguro de si los elementos son únicos, simplemente use la configuración predeterminada de NumPy's
setdiff1den las soluciones A y B. ¿Qué puede ser un ejemplo de complicación? Ver nota (c).(c) Las cosas serán diferentes si cualquiera de las dos listas no es única.
Por ejemplo
list_2no es único:list2 = ["a", "f", "c", "m", "m"]. Mantenerlist1como está:list_1 = ["a", "b", "c", "d", "e"]establecer el valor predeterminado de los
assume_uniquerendimientos["f", "m"](en ambas soluciones). SIN EMBARGO, si estableceassume_unique=True, ambas soluciones dan["f", "m", "m"]. ¿Por qué? Esto se debe a que el usuario asumió que los elementos son únicos). Por lo tanto, es mejor mantenerassume_uniquea su valor predeterminado. Tenga en cuenta que ambas respuestas están ordenadas.pitónnumpy
fuente
Puedes usar conjuntos:
Salida:
Según el comentario de @JonClements, aquí hay una versión más ordenada:
fuente
uniqueelementos, pero ¿qué pasa si tenemos múltiples,m'spor ejemplo, esto no lo recogería?list(set(list_2).difference(list_1))que evita lasetconversión explícita ...No estoy seguro de por qué las explicaciones anteriores son tan complicadas cuando tiene métodos nativos disponibles:
fuente
Use una lista de comprensión como esta:
Salida:
Editar:
Como se menciona en los comentarios a continuación, con grandes listas, lo anterior no es la solución ideal. Cuando ese es el caso, una mejor opción sería convertir
list_1a unasetprimera:fuente
list_1, querrá realizar una conversión previa aset/frozenset, por ejemploset_1 = frozenset(list_1), luegomain_list = [item for item in list_2 if item not in set_1], reduciendo el tiempo de verificación deO(n)por elemento a (aproximadamente)O(1).enumerate()para eso:[index for (index, item) in enumerate(list_2) if item not in list_1]Si desea una solución de una línea (ignorando las importaciones) que solo requiere
O(max(n, m))trabajo para entradas de longitudnym, noO(n * m)trabajo, puede hacerlo con elitertoolsmódulo :Esto aprovecha las funciones funcionales que toman una función de devolución de llamada en la construcción, lo que le permite crear la devolución de llamada una vez y reutilizarla para cada elemento sin necesidad de almacenarla en algún lugar (porque la
filterfalsealmacena internamente); las comprensiones de listas y las expresiones generadoras pueden hacer esto, pero es feo. †Eso obtiene los mismos resultados en una sola línea que:
con la velocidad de:
Por supuesto, si las comparaciones están destinadas a ser posicionales, entonces:
debe producir:
(debido a que el valor en
list_2tiene una coincidencia en el mismo índice enlist_1), definitivamente debe ir con la respuesta de Patrick , que no implica unalists osets temporal (incluso sisets es más o menosO(1), tienen un factor "constante" más alto por verificación que las simples verificaciones de igualdad ) e implicaO(min(n, m))trabajo, menos que cualquier otra respuesta, y si su problema es sensible a la posición, es la única solución correcta cuando los elementos coincidentes aparecen en desplazamientos no coincidentes.†: La forma de hacer lo mismo con una comprensión de la lista como una línea sería abusar del bucle anidado para crear y almacenar valores en el bucle "más externo", por ejemplo:
lo que también proporciona un beneficio de rendimiento menor en Python 3 (porque ahora
set_1tiene un alcance local en el código de comprensión, en lugar de buscarlo desde el alcance anidado para cada verificación; en Python 2 eso no importa, porque Python 2 no usa cierres para enumere las comprensiones; operan en el mismo ámbito en el que se usan).fuente
salida:
fuente
list_1es grande ylist_2no tiene un tamaño trivial, porque implicalen(list_2)O(n)escaneos delist_1, haciéndoloO(n * m)(dóndenymson las longitudes delist_2ylist_1respectivamente). Si conviertelist_1aset/frozensetpor adelantado, las comprobaciones de contención se pueden realizarO(1), haciendo que el trabajo total seaO(n)de la longitud delist_2(técnicamenteO(max(n, m)), ya queO(m)trabaja para hacer elset).Yo haría
ziplas listas juntas para compararlas elemento por elemento.fuente
lists con un solo nuevolistconstruido, sin temporarios adicionales , sin costosos controles de contención, etc.Usé dos métodos y encontré un método útil sobre otro. Aquí está mi respuesta:
Mis datos de entrada:
Método 1:
np.setdiff1dme gusta este enfoque sobre otro porque conserva la posiciónMétodo 2: aunque da la misma respuesta que en el Método 1 pero perturba el orden
Method1
np.setdiff1dcumple mis requisitos perfectamente. Esta respuesta para información.fuente
Si se debe tener en cuenta el número de ocurrencias, probablemente necesite usar algo como
collections.Counter:Como se prometió, esto también puede manejar diferentes números de ocurrencias como "diferencia":
fuente
De ser1 elimine los elementos presentes en ser2.
Entrada
ser1 = pd.Series ([1, 2, 3, 4, 5]) ser2 = pd.Series ([4, 5, 6, 7, 8])
Solución
ser1 [~ ser1.isin (ser2)]
fuente