J'ai besoin de 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 veux parcourir list_1 et ajouter à main_list tous les éléments de list_2 qui ne se trouvent pas dans list_1.
Le résultat devrait être:
main_list=["f", "m"]
Comment puis-je le faire avec python?
list_2
qui n'apparaissent nulle part danslist_1
ou des éléments danslist_2
qui ne sont pas présents dans le même index danslist_1
?Réponses:
TL; DR:
SOLUTION (1)
SOLUTION (2) Vous voulez une liste triée
EXPLICATION:
(1) Vous pouvez utiliser de NumPy
setdiff1d
(array1
,array2
,assume_unique
=False
).assume_unique
demande à l'utilisateur SI les tableaux SONT DÉJÀ UNIQUES.Si
False
, alors les éléments uniques sont déterminés en premier.Si
True
, la fonction supposera que les éléments sont déjà uniques ET la fonction ignorera la détermination des éléments uniques.Cela donne les valeurs uniques dans
array1
qui ne sont pas dansarray2
.assume_unique
estFalse
par défaut.Si vous êtes concerné par les éléments uniques (en fonction de la réponse de Chinny84 ), utilisez simplement (où
assume_unique=False
=> la valeur par défaut):(2) Pour ceux qui souhaitent que les réponses soient triées, j'ai créé une fonction personnalisée:
Pour obtenir la réponse, exécutez:
REMARQUES SUPPLÉMENTAIRES:
(a) La solution 2 (fonction personnalisée
setdiff_sorted
) renvoie une liste (comparée à un tableau dans la solution 1).(b) Si vous n'êtes pas sûr que les éléments soient uniques, utilisez simplement le paramètre par défaut de NumPy's
setdiff1d
dans les deux solutions A et B. Qu'est-ce qui peut être un exemple de complication? Voir note (c).(c) Les choses seront différentes si l'une des deux listes n'est pas unique.
Say
list_2
est pas unique:list2 = ["a", "f", "c", "m", "m"]
. Conserverlist1
tel quel :list_1 = ["a", "b", "c", "d", "e"]
Définition de la valeur par défaut des
assume_unique
rendements["f", "m"]
(dans les deux solutions). CEPENDANT, si vous définissezassume_unique=True
, les deux solutions donnent["f", "m", "m"]
. Pourquoi? C'est parce que l'utilisateur a supposé que les éléments sont uniques). Par conséquent, il vaut mieux garderassume_unique
à sa valeur par défaut. Notez que les deux réponses sont triées.pythonengourdi
la source
Vous pouvez utiliser des ensembles:
Production:
Par commentaire de @JonClements, voici une version plus ordonnée:
la source
unique
éléments, mais que se passe-t-il si nous en avons plusieurs,m's
par exemple, cela ne les prendrait pas.list(set(list_2).difference(list_1))
cela évite laset
conversion explicite ...Je ne sais pas pourquoi les explications ci-dessus sont si compliquées lorsque vous avez des méthodes natives disponibles:
la source
Utilisez une compréhension de liste comme celle-ci:
Production:
Éditer:
Comme mentionné dans les commentaires ci-dessous, avec de grandes listes, ce qui précède n'est pas la solution idéale. Lorsque c'est le cas, une meilleure option serait de convertir
list_1
en uneset
première:la source
list_1
, vous voudriez preconvert à unset
/frozenset
, par exempleset_1 = frozenset(list_1)
, puismain_list = [item for item in list_2 if item not in set_1]
, ce qui réduit le temps de vérification deO(n)
par article à (environ)O(1)
.enumerate()
pour cela:[index for (index, item) in enumerate(list_2) if item not in list_1]
Si vous voulez une solution à une ligne (en ignorant les importations) qui ne nécessite que du
O(max(n, m))
travail pour les entrées de longueurn
etm
, pas duO(n * m)
travail, vous pouvez le faire avec leitertools
module :Cela tire parti des fonctions fonctionnelles prenant une fonction de rappel lors de la construction, lui permettant de créer le rappel une fois et de le réutiliser pour chaque élément sans avoir besoin de le stocker quelque part (car le
filterfalse
stocke en interne); les compréhensions de listes et les expressions génératrices peuvent le faire, mais c'est moche. †Cela donne les mêmes résultats en une seule ligne que:
à la vitesse de:
Bien sûr, si les comparaisons sont destinées à être positionnelles, alors:
devrait produire:
(car aucune valeur dans
list_2
n'a une correspondance au même index danslist_1
), vous devriez certainement aller avec la réponse de Patrick , qui n'implique aucunlist
s ouset
s temporaire (même avecset
s étant à peu prèsO(1)
, ils ont un facteur «constant» par vérification plus élevé que la simple égalité vérifie) et implique duO(min(n, m))
travail, moins que toute autre réponse, et si votre problème est sensible à la position, est la seule solution correcte lorsque des éléments correspondants apparaissent à des décalages incompatibles.†: La façon de faire la même chose avec une compréhension de liste qu'une seule ligne serait d'abuser de la boucle imbriquée pour créer et mettre en cache des valeurs dans la boucle "la plus externe", par exemple:
ce qui donne également un avantage mineur en termes de performances sur Python 3 (car il
set_1
est désormais défini localement dans le code de compréhension, plutôt que de rechercher à partir de la portée imbriquée pour chaque vérification; sur Python 2, cela n'a pas d'importance, car Python 2 n'utilise pas de fermetures pour list comprehensions; ils opèrent dans la même portée dans laquelle ils sont utilisés).la source
production:
la source
list_1
est grande etlist_2
est de taille non triviale, car elle implique deslen(list_2)
O(n)
analyses delist_1
, la créationO(n * m)
(oùn
etm
sont les longueurs delist_2
etlist_1
respectivement). Si vous convertissezlist_1
enset
/frozenset
à l'avant, les contrôles de contenu peuvent être effectuésO(1)
, ce qui rend le travail totalO(n)
sur la longueur delist_2
(techniquementO(max(n, m))
, puisque vousO(m)
travaillez pour faire leset
).Je voudrais
zip
les listes ensemble pour les comparer élément par élément.la source
list
avec un seul nouveau enlist
cours de construction, pas de temporaires supplémentaires , pas de contrôles de confinement coûteux, etc.J'ai utilisé deux méthodes et j'ai trouvé une méthode plus utile qu'une autre. Voici ma réponse:
Mes données d'entrée:
Méthode 1:
np.setdiff1d
J'aime cette approche par rapport à une autre car elle préserve la positionMéthode 2: bien qu'elle donne la même réponse que dans la méthode 1 mais perturbe l'ordre
Method1
np.setdiff1d
répond parfaitement à mes exigences. Cette réponse pour information.la source
Si le nombre d'occurrences doit être pris en compte, vous devez probablement utiliser quelque chose comme
collections.Counter
:Comme promis, cela peut également traiter un nombre différent d'occurrences comme une «différence»:
la source
À partir de ser1, supprimez les éléments présents dans ser2.
Contribution
ser1 = pd.Series ([1, 2, 3, 4, 5]) ser2 = pd.Series ([4, 5, 6, 7, 8])
Solution
ser1 [~ ser1.isin (ser2)]
la source