308 votes

Python trouve des éléments dans une liste qui ne sont pas dans l'autre

Je dois comparer deux listes afin de créer une nouvelle liste d'éléments spécifiques trouvés dans une liste mais pas dans l'autre. Par exemple:

 main_list=[]
list_1=["a", "b", "c", "d", "e"]
list_2=["a", "f", "c", "m"] 
 

Je souhaite parcourir list_1 et ajouter à main_list tous les éléments de list_2 qui ne figurent pas dans list_1.

Le résultat devrait être:

 main_list=["f", "m"]
 

Comment puis-je le faire avec python?

433voto

nrlakin Points 951

Vous pouvez utiliser des ensembles:

 main_list = list(set(list_2) - set(list_1))
 

Sortie:

 >>> list_1=["a", "b", "c", "d", "e"]
>>> list_2=["a", "f", "c", "m"]
>>> set(list_2) - set(list_1)
set(['m', 'f'])
>>> list(set(list_2) - set(list_1))
['m', 'f']
 

D'après le commentaire de @JonClements, voici une version plus ordonnée:

 >>> list_1=["a", "b", "c", "d", "e"]
>>> list_2=["a", "f", "c", "m"]
>>> list(set(list_2).difference(list_1))
['m', 'f']
 

201voto

jpmaulion Points 386

(1) Vous pouvez utiliser NumPy l' setdiff1d. À partir de la réponse de Chinny84, si vous êtes concernés par les uniques éléments, puis:

import numpy as np
list_1 = ["a", "b", "c", "d", "e"]
list_2 = ["a", "f", "c", "m"] 
main_list = np.setdiff1d(list_2,list_1)

(2) Sinon, utilisez main_list = np.setdiff1d(list_2,list_1, assume_unique=True)

Les deux réponses vous donneront ["f", "m"]. Toutefois, si list_2 = ["a", "f", "c", "m", "m"], la réponse (1) les rendements en ["f", "m"] MAIS la réponse (2) donne ["f", "m", "m"] (en raison de l'unicité de chaque élément en list_2 est négligeable).

93voto

ettanany Points 9471

Utilisez une liste de compréhension comme celle-ci:

 main_list = [item for item in list_2 if item not in list_1]
 

Sortie:

 >>> list_1 = ["a", "b", "c", "d", "e"]
>>> list_2 = ["a", "f", "c", "m"] 
>>> 
>>> main_list = [item for item in list_2 if item not in list_1]
>>> main_list
['f', 'm']
 

87voto

A.Kot Points 3343

Vous ne savez pas pourquoi les explications ci-dessus sont si compliquées quand vous avez des méthodes natives disponibles:

 main_list = list(set(list_2)-set(list_1))
 

12voto

ShadowRanger Points 44

Si vous voulez un one-liner solution (en ignorant les importations) qui ne nécessite qu' O(max(n, m)) de travail pour les entrées de longueur n et m, pas O(n * m) de travail, vous pouvez le faire avec l' itertools module de:

from itertools import filterfalse

main_list = list(filterfalse(set(list_1).__contains__, list_2))

Cette méthode tire parti de la fonctionnelle de fonctions une fonction de rappel de la construction, afin de créer la fonction de rappel une fois et de le réutiliser pour chaque élément, sans avoir besoin de le stocker quelque part (parce qu' filterfalse magasins en interne); interprétations de la liste et le générateur d'expressions peut le faire, mais c'est moche.†

Qui obtient les mêmes résultats en une seule ligne:

main_list = [x for x in list_2 if x not in list_1]

avec la vitesse de:

set_1 = set(list_1)
main_list = [x for x in list_2 if x not in set_1]

Bien sûr, si les comparaisons sont destinés à être de position, de sorte que:

list_1 = [1, 2, 3]
list_2 = [2, 3, 4]

doit produire:

main_list = [2, 3, 4]

(parce que la valeur en list_2 a un match à la même indice en list_1), vous devriez certainement aller avec Patrick réponse, ce qui n'implique pas de temporaire lists ou sets (même avec sets d'être à peu près O(1), ils ont plus de "constante" facteur par vérifier que de simples contrôles d'égalité) et implique O(min(n, m)) le travail, moins que toute autre réponse, et si votre problème est sensible à la position, est la seule correcte de la solution lors de l'appariement des éléments apparaissent à incompatibles décalages.

†: La façon de faire la même chose avec une compréhension de liste comme un one-liner serait de l'abus de boucle imbriquée pour créer et mettre en cache les valeur(s) dans la "ultrapériphériques" de la boucle, par exemple:

main_list = [x for set_1 in (set(list_1),) for x in list_2 if x not in set_1]

qui donne également un mineur avantage de performance sur Python 3 (parce que maintenant, en set_1 est configuré localement dans la compréhension du code, plutôt que d'leva les yeux de imbriquée à la portée de chaque case; sur Python 2 qui n'a pas d'importance, parce que Python 2 ne pas utiliser des fermetures pour les interprétations de la liste; ils fonctionnent de la même portée, ils sont utilisés dans des).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X