Comment puis-je trouver les doublons dans une liste Python et créer une autre liste des doublons? La liste ne contient que des entiers.
439
Comment puis-je trouver les doublons dans une liste Python et créer une autre liste des doublons? La liste ne contient que des entiers.
Réponses:
Pour supprimer les doublons, utilisez
set(a)
. Pour imprimer des doublons, quelque chose comme:Notez que ce
Counter
n'est pas particulièrement efficace ( timings ) et probablement exagéré ici.set
fonctionnera mieux. Ce code calcule une liste d'éléments uniques dans l'ordre source:ou, plus concis:
Je ne recommande pas ce dernier style, car ce n'est pas évident
not seen.add(x)
(laadd()
méthode set revient toujoursNone
, d'où la nécessiténot
).Pour calculer la liste des éléments dupliqués sans bibliothèques:
Si les éléments de la liste ne sont pas hachables, vous ne pouvez pas utiliser d'ensembles / dict et devez recourir à une solution temporelle quadratique (comparer chacun avec chacun). Par exemple:
la source
O(n)
, car il n'itère la liste qu'une seule fois et les recherches définies le sontO(1)
.dup = []
else: dup.append(x)
print()
seen = set()
puisdupe = set(x for x in a if x in seen or seen.add(x))
la source
l
parset(l)
ne réduit que la complexité temporelle la plus défavorable et ne fait donc rien pour résoudre les problèmes d'efficacité à plus grande échelle avec cette réponse. Ce n'était probablement pas si simple après tout. Bref, ne faites pas ça.Vous n'avez pas besoin du nombre, juste si l'article a été vu auparavant ou non. Adapté cette réponse à ce problème:
Juste au cas où la vitesse compte, voici quelques timings:
Voici les résultats: (bravo @JohnLaRooy!)
Fait intéressant, outre le timing lui-même, le classement change également légèrement lorsque Pypy est utilisé. Plus intéressant encore, l'approche Counter-based bénéficie énormément des optimisations de Pypy, tandis que l'approche de mise en cache de méthode que j'ai suggérée semble n'avoir presque aucun effet.
Apparemment, cet effet est lié à la "duplication" des données d'entrée. J'ai défini
l = [random.randrange(1000000) for i in xrange(10000)]
et obtenu ces résultats:la source
add
chaque fois qu'une insertion sera nécessaire.pypy
si vous l'avez à portée de main et que vous allez pour la vitesse.Vous pouvez utiliser
iteration_utilities.duplicates
:ou si vous ne voulez qu'un seul de chaque doublon, cela peut être combiné avec
iteration_utilities.unique_everseen
:Il peut également gérer des éléments non lavables (mais au détriment des performances):
C'est quelque chose que seules quelques-unes des autres approches ici peuvent gérer.
Repères
J'ai fait un benchmark rapide contenant la plupart (mais pas toutes) des approches mentionnées ici.
Le premier repère ne comprenait qu'une petite gamme de longueurs de liste car certaines approches
O(n**2)
comportement.Dans les graphiques, l'axe des y représente le temps, donc une valeur inférieure signifie mieux. Il est également tracé le journal de bord afin que la large gamme de valeurs puisse être mieux visualisée:
En supprimant les
O(n**2)
approches, j'ai fait un autre benchmark jusqu'à un demi-million d'éléments dans une liste:Comme vous pouvez le voir, l'
iteration_utilities.duplicates
approche est plus rapide que toutes les autres approches et même le chaînageunique_everseen(duplicates(...))
était plus rapide ou aussi rapide que les autres approches.Une autre chose intéressante à noter ici est que les approches des pandas sont très lentes pour les petites listes mais peuvent facilement rivaliser pour les listes plus longues.
Cependant, comme ces tests de référence montrent que la plupart des approches fonctionnent à peu près de la même manière, peu importe laquelle est utilisée (à l'exception des 3 qui avaient un
O(n**2)
temps d'exécution).Benchmark 1
Repère 2
Avertissement
1 Ceci est d'une bibliothèque tierce , je l' ai écrit:
iteration_utilities
.la source
Je suis tombé sur cette question en regardant quelque chose de connexe - et je me demande pourquoi personne n'a offert une solution basée sur un générateur? Résoudre ce problème serait:
J'étais préoccupé par l'évolutivité, j'ai donc testé plusieurs approches, y compris des éléments naïfs qui fonctionnent bien sur de petites listes, mais évoluent horriblement à mesure que les listes s'agrandissent (note - il aurait été préférable d'utiliser timeit, mais cela est illustratif).
J'ai inclus @moooeeeep pour comparaison (c'est incroyablement rapide: plus rapide si la liste d'entrée est complètement aléatoire) et une approche itertools qui est encore plus rapide pour les listes principalement triées ... Inclut maintenant l'approche pandas de @firelynx - lente, mais pas horriblement et simple. Remarque - l'approche tri / tee / zip est toujours la plus rapide sur ma machine pour les grandes listes principalement commandées, moooeeeep est la plus rapide pour les listes mélangées, mais votre kilométrage peut varier.
Les avantages
Hypothèses
Solution la plus rapide, 1m d'entrées:
Approches testées
Les résultats pour le test «toutes les dupes» étaient cohérents, trouvant «premier» doublon puis «tous» les doublons dans ce tableau:
Lorsque les listes sont mélangées en premier, le prix du tri devient apparent - l'efficacité chute sensiblement et l'approche @moooeeeep domine, les approches set & dict étant similaires mais moins performantes:
la source
random.shuffle(c)
en tenir compte. De plus, je ne peux pas non plus répliquer vos résultats lors de l'exécution du script non modifié (ordre totalement différent), donc cela dépend peut-être aussi du CPU.Utilisation de pandas:
la source
collections.Counter est nouveau en python 2.7:
Dans une version antérieure, vous pouvez utiliser un dict classique à la place:
la source
Voici une solution nette et concise -
la source
Je le ferais avec des pandas, car j'utilise beaucoup de pandas
Donne
Ce n'est probablement pas très efficace, mais c'est certainement moins de code que la plupart des autres réponses, alors j'ai pensé contribuer
la source
pda = pd.Series(a)
print list(pda[pda.duplicated()])
Sans convertir en liste et probablement le moyen le plus simple serait quelque chose comme ci-dessous. Cela peut être utile lors d'un entretien quand ils demandent de ne pas utiliser d'ensembles
======= else pour obtenir 2 listes distinctes de valeurs uniques et de valeurs en double
la source
le troisième exemple de la réponse acceptée donne une réponse erronée et n'essaie pas de donner des doublons. Voici la bonne version:
la source
Que diriez-vous simplement de parcourir chaque élément de la liste en vérifiant le nombre d'occurrences, puis en les ajoutant à un ensemble qui imprimera ensuite les doublons. J'espère que cela aide quelqu'un là-bas.
la source
Nous pouvons utiliser
itertools.groupby
afin de trouver tous les articles qui ont des doublons:La sortie sera:
la source
dupes = [x for x, y in groupby(sorted(myList)) if len(list(y)) > 1]
Je suppose que le moyen le plus efficace de trouver des doublons dans une liste est:
Il utilise
Counter
tous les éléments et tous les éléments uniques. Soustraire le premier au second ne laissera de côté que les doublons.la source
Un peu tard, mais peut-être utile pour certains. Pour une liste assez longue, j'ai trouvé que cela fonctionnait pour moi.
Affiche juste et tous les doublons et préserve l'ordre.
la source
Un moyen très simple et rapide de trouver des dupes avec une seule itération en Python est:
La sortie sera la suivante:
Ceci et plus dans mon blog http://www.howtoprogramwithpython.com
la source
J'entre beaucoup plus tard dans cette discussion. Même si, je voudrais traiter ce problème avec un liners. Parce que c'est le charme de Python. si nous voulons simplement obtenir les doublons dans une liste séparée (ou n'importe quelle collection), je suggère de faire comme ci-dessous. Dites que nous avons une liste dupliquée que nous pouvons appeler comme `` cible ''
Maintenant, si nous voulons obtenir les doublons, nous pouvons utiliser la doublure comme ci-dessous:
Ce code mettra les enregistrements dupliqués comme clé et comptera comme valeur dans le dictionnaire 'duplicates'. Le dictionnaire 'duplicate' ressemblera à ce qui suit:
Si vous voulez juste tous les enregistrements avec des doublons seuls dans une liste, son code est encore beaucoup plus court:
La sortie sera:
Cela fonctionne parfaitement dans les versions python 2.7.x +
la source
Python 3.8 one-liner si vous ne vous souciez pas d'écrire votre propre algorithme ou d'utiliser des bibliothèques:
Imprime l'élément et compte:
groupby
prend une fonction de regroupement afin que vous puissiez définir vos regroupements de différentes manières et renvoyer des informations supplémentairesTuple
champs si nécessaire.groupby
est paresseux donc ça ne devrait pas être trop lent.la source
Quelques autres tests. Bien sûr à faire ...
... est trop coûteux. C'est environ 500 fois plus rapide (le tableau le plus long donne de meilleurs résultats) pour utiliser la méthode finale suivante:
Seulement 2 boucles, pas très coûteuses
l.count()
opérations .Voici un code pour comparer les méthodes par exemple. Le code est ci-dessous, voici la sortie:
Le code de test:
la source
Méthode 1:
Explication: [val pour idx, val en énumération (liste_entrée) si val dans liste_entrée [idx + 1:]] est une compréhension de liste, qui renvoie un élément, si le même élément est présent à partir de sa position actuelle, dans la liste, l'index .
Exemple: liste_entrées = [42,31,42,31,3,31,31,5,6,6,6,6,6,7,42]
en commençant par le premier élément de la liste, 42, avec l'index 0, il vérifie si l'élément 42 est présent dans input_list [1:] (c'est-à-dire de l'index 1 jusqu'à la fin de la liste) Parce que 42 est présent dans input_list [1:] , il retournera 42.
Ensuite, il passe à l'élément suivant 31, avec l'index 1, et vérifie si l'élément 31 est présent dans la liste_entrée [2:] (c'est-à-dire de l'index 2 jusqu'à la fin de la liste), Parce que 31 est présent dans la liste_entrée [2:], il reviendra 31.
de même, il parcourt tous les éléments de la liste et ne renvoie que les éléments répétés / en double dans une liste.
Ensuite, parce que nous avons des doublons, dans une liste, nous devons choisir un de chaque doublon, c'est-à-dire supprimer le doublon parmi les doublons, et pour ce faire, nous appelons un ensemble nommé python nommé set (), et il supprime les doublons,
Ensuite, nous nous retrouvons avec un ensemble, mais pas une liste, et donc pour convertir d'un ensemble en liste, nous utilisons, le transtypage, list (), et qui convertit l'ensemble des éléments en une liste.
Méthode 2:
Explication: Ici, nous créons deux listes vides, pour commencer. Continuez ensuite à parcourir tous les éléments de la liste, pour voir si elle existe dans temp_list (initialement vide). S'il n'est pas là dans la temp_list, alors nous l'ajoutons à la temp_list, en utilisant la méthode append .
S'il existe déjà dans temp_list, cela signifie que l'élément courant de la liste est un doublon, et donc nous devons l'ajouter à dupe_list en utilisant la méthode append .
la source
Vous supprimez essentiellement les doublons en les convertissant en set (
clean_list
), puis en itérant leraw_list
, tout en supprimant chacunitem
dans la liste claire pour l'occurrence dansraw_list
. S'ilitem
n'est pas trouvé, l'ValueError
exception déclenchée est interceptée etitem
ajoutée à laduplicated_items
liste.Si l'index des éléments dupliqués est nécessaire, juste
enumerate
la liste et jouer avec l'index. (for index, item in enumerate(raw_list):
) qui est plus rapide et optimisé pour les grandes listes (comme des milliers + d'éléments)la source
utilisation d'une
list.count()
méthode dans la liste pour trouver les éléments en double d'une liste donnéela source
une ligne, pour le plaisir, et où une seule déclaration est requise.
la source
la source
Solution en une ligne:
la source
Il y a beaucoup de réponses ici, mais je pense que c'est relativement une approche très lisible et facile à comprendre:
Remarques:
la source
Voici un générateur rapide qui utilise un dict pour stocker chaque élément sous forme de clé avec une valeur booléenne pour vérifier si l'élément en double a déjà été généré.
Pour les listes avec tous les éléments qui sont des types hachables:
Pour les listes pouvant contenir des listes:
la source
la source
Lors de l'utilisation de toolz :
la source
c'est ainsi que je devais le faire car je me suis mis au défi de ne pas utiliser d'autres méthodes:
pour que votre échantillon fonctionne comme:
la source
duplist = list(set(a))
.