À peu près, j'ai besoin d'écrire un programme pour vérifier si une liste contient des doublons et s'il le fait, il les supprime et renvoie une nouvelle liste avec les éléments qui n'ont pas été dupliqués / supprimés. C'est ce que j'ai mais pour être honnête je ne sais pas quoi faire.
def remove_duplicates():
t = ['a', 'b', 'c', 'd']
t2 = ['a', 'c', 'd']
for t in t2:
t.append(t.remove())
return t
python
algorithm
list
duplicates
intersection
Neemaximo
la source
la source
Réponses:
L'approche courante pour obtenir une collection unique d'articles est d'utiliser a
set
. Les ensembles sont des collections non ordonnées d' objets distincts . Pour créer un ensemble à partir de n'importe quel itérable, vous pouvez simplement le passer à laset()
fonction intégrée. Si vous avez besoin ultérieurement d'une vraie liste, vous pouvez également transmettre l'ensemble à lalist()
fonction.L'exemple suivant doit couvrir tout ce que vous essayez de faire:
Comme vous pouvez le voir dans l'exemple de résultat, la commande d'origine n'est pas conservée . Comme mentionné ci-dessus, les ensembles eux-mêmes sont des collections non ordonnées, donc la commande est perdue. Lors de la reconversion d'un ensemble en liste, un ordre arbitraire est créé.
Maintenir l'ordre
Si l'ordre est important pour vous, vous devrez utiliser un mécanisme différent. Une solution très courante pour cela consiste à s'appuyer sur
OrderedDict
pour conserver l'ordre des clés lors de l'insertion:À partir de Python 3.7 , le dictionnaire intégré est également garanti de maintenir l'ordre d'insertion, vous pouvez donc également l'utiliser directement si vous êtes sur Python 3.7 ou version ultérieure (ou CPython 3.6):
Notez que cela peut entraîner une surcharge de création d'un dictionnaire, puis de création d'une liste à partir de celui-ci. Si vous n'avez pas réellement besoin de conserver l'ordre, il vaut souvent mieux utiliser un ensemble, surtout parce qu'il vous donne beaucoup plus d'opérations avec lesquelles travailler. Consultez cette question pour plus de détails et d'autres moyens de préserver l'ordre lors de la suppression des doublons.
Enfin, notez que les solutions
set
aussi bien queOrderedDict
/dict
nécessitent que vos articles soient lavables . Cela signifie généralement qu'ils doivent être immuables. Si vous devez gérer des éléments qui ne sont pas hachables (par exemple, lister des objets), vous devrez utiliser une approche lente dans laquelle vous devrez essentiellement comparer chaque élément avec tous les autres éléments dans une boucle imbriquée.la source
Dans Python 2.7 , la nouvelle façon de supprimer les doublons d'un itérable tout en le conservant dans l'ordre d'origine est:
Dans Python 3.5 , OrderedDict a une implémentation C. Mes synchronisations montrent que c'est maintenant à la fois la plus rapide et la plus courte des différentes approches pour Python 3.5.
En Python 3.6 , le dict régulier est devenu à la fois ordonné et compact. (Cette fonctionnalité est valable pour CPython et PyPy mais peut ne pas être présente dans d'autres implémentations). Cela nous donne un nouveau moyen de déduplication le plus rapide tout en conservant l'ordre:
Dans Python 3.7 , le dict régulier est garanti à la fois ordonné dans toutes les implémentations. Ainsi, la solution la plus courte et la plus rapide est:
la source
TypeError: unhashable type: 'dictlist'
C'est un vol simple:
list(set(source_list))
fera l'affaire.A
set
est quelque chose qui ne peut pas avoir de doublons.Mise à jour: une approche qui préserve l'ordre est de deux lignes:
Ici, nous utilisons le fait qui se
OrderedDict
souvient de l'ordre d'insertion des clés et ne le change pas lorsqu'une valeur à une clé particulière est mise à jour. Nous insérons enTrue
tant que valeurs, mais nous pourrions insérer n'importe quoi, les valeurs ne sont tout simplement pas utilisées. (set
fonctionne un peu comme undict
avec des valeurs ignorées aussi.)la source
source_list
est lavable.la source
frozenset
fonctionne avec du contenu non hachable. J'obtiens toujours l'erreur non-hachable lors de l'utilisationfrozenset
.Si vous ne vous souciez pas de la commande, faites simplement ceci:
A
set
est garanti de ne pas avoir de doublons.la source
l
est lavable.Pour créer une nouvelle liste en conservant l'ordre des premiers éléments des doublons dans
L
newlist=[ii for n,ii in enumerate(L) if ii not in L[:n]]
par exemple
if L=[1, 2, 2, 3, 4, 2, 4, 3, 5]
alorsnewlist
sera[1,2,3,4,5]
Ceci vérifie que chaque nouvel élément n'est pas apparu précédemment dans la liste avant de l'ajouter. De plus, il n'a pas besoin d'importations.
la source
set
etOrderedDict
peuvent avoir une complexité de temps amorti inférieure.Un collègue m'a envoyé la réponse acceptée dans le cadre de son code pour une révision du code aujourd'hui. Bien que j'admire certainement l'élégance de la réponse en question, je ne suis pas satisfait de la performance. J'ai essayé cette solution (j'utilise set pour réduire le temps de recherche)
Pour comparer l'efficacité, j'ai utilisé un échantillon aléatoire de 100 entiers - 62 étaient uniques
Voici les résultats des mesures
Eh bien, que se passe-t-il si l'ensemble est supprimé de la solution?
Le résultat n'est pas aussi mauvais qu'avec le OrderedDict , mais toujours plus de 3 fois la solution d'origine
la source
def unique(iterable):
:;seen = set()
;seen_add = seen.add
;return [item for item in iterable if not item in seen and not seen_add(item)]
Il existe également des solutions utilisant Pandas et Numpy. Ils renvoient tous les deux un tableau numpy, vous devez donc utiliser la fonction
.tolist()
si vous voulez une liste.Solution Pandas
Utilisation de la fonction Pandas
unique()
:Solution Numpy
Utilisation de la fonction numpy
unique()
.Notez que numpy.unique () trie également les valeurs . La liste
t2
est donc retournée triée. Si vous souhaitez que l'ordre soit préservé, utilisez comme dans cette réponse :La solution n'est pas aussi élégante par rapport aux autres, cependant, par rapport à pandas.unique (), numpy.unique () vous permet également de vérifier si les tableaux imbriqués sont uniques le long d'un axe sélectionné.
la source
Une autre façon de faire:
la source
keys()
retourne un objet de vue de dictionnaire, pas une liste.Simple et facile:
Production:
la source
in
est une opération O (n) et vouscleanlist
aurez au plus desn
nombres => pire des cas ~ O (n ^ 2)Dans cette réponse, il y aura deux sections: deux solutions uniques et un graphique de vitesse pour des solutions spécifiques.
Suppression des éléments en double
La plupart de ces réponses ne suppriment que les éléments en double qui sont lavables , mais cette question n'implique pas qu'il n'a pas seulement besoin d' éléments lavables , ce qui signifie que je proposerai des solutions qui ne nécessitent pas de nettoyage. articles .
collections.Counter est un outil puissant dans la bibliothèque standard qui pourrait être parfait pour cela. Il n'y a qu'une seule autre solution qui contient même Counter. Cependant, cette solution est également limitée à hashable clés .
Pour autoriser les clés non partageables dans Counter, j'ai créé une classe Container, qui essaiera d'obtenir la fonction de hachage par défaut de l'objet, mais si elle échoue, elle essaiera sa fonction d'identité. Il définit également un eq et une méthode de hachage . Cela devrait être suffisant pour autoriser les éléments non lavables dans notre solution. Les objets non lavables seront traités comme s'ils étaient lavables. Cependant, cette fonction de hachage utilise l'identité pour les objets non lavables, ce qui signifie que deux objets égaux qui sont tous les deux non lavables ne fonctionneront pas. Je vous suggère de remplacer cela et de le changer pour utiliser le hachage d'un type mutable équivalent (comme utiliser
hash(tuple(my_list))
ifmy_list
est une liste).J'ai également fait deux solutions. Une autre solution qui conserve l'ordre des articles, en utilisant une sous-classe à la fois OrderedDict et Counter qui est nommée 'OrderedCounter'. Maintenant, voici les fonctions:
remd est un tri non ordonné, oremd est un tri ordonné. Vous pouvez clairement dire lequel est le plus rapide, mais je l'expliquerai quand même. Le tri non ordonné est légèrement plus rapide. Il conserve moins de données, car il n'a pas besoin de commande.
Maintenant, je voulais aussi montrer les comparaisons de vitesse de chaque réponse. Donc, je vais le faire maintenant.
Quelle fonction est la plus rapide?
Pour supprimer les doublons, j'ai rassemblé 10 fonctions à partir de quelques réponses. J'ai calculé la vitesse de chaque fonction et l'ai mise dans un graphique en utilisant matplotlib.pyplot .
J'ai divisé cela en trois séries de graphiques. Un hachable est tout objet qui peut être haché, un non lavable est tout objet qui ne peut pas être haché. Une séquence ordonnée est une séquence qui préserve l'ordre, une séquence non ordonnée ne préserve pas l'ordre. Maintenant, voici quelques termes supplémentaires:
Unordered Hashable était pour toute méthode qui supprimait les doublons, qui ne devait pas nécessairement conserver la commande. Cela ne devait pas fonctionner pour les incontrôlables, mais cela pouvait.
Commandé Hashable était pour n'importe quelle méthode qui gardait l'ordre des articles dans la liste, mais cela ne devait pas fonctionner pour les éléments non modifiables, mais c'était possible.
Ordered Unhashable était une méthode qui maintenait l'ordre des éléments dans la liste et fonctionnait pour les éléments non partageables.
Sur l'axe des y est le nombre de secondes qu'il a fallu.
Sur l'axe des x se trouve le nombre auquel la fonction a été appliquée.
Nous avons généré des séquences de hashables non ordonnées et ordonnées hashables avec la compréhension suivante:
[list(range(x)) + list(range(x)) for x in range(0, 1000, 10)]
Pour les éléments non partagés commandés:
[[list(range(y)) + list(range(y)) for y in range(x)] for x in range(0, 1000, 10)]
Notez qu'il y a une «étape» dans la plage, car sans elle, cela aurait pris 10 fois plus de temps. Aussi parce qu'à mon avis, je pensais que ça aurait pu paraître un peu plus facile à lire.
Notez également que les touches de la légende sont ce que j'ai essayé de deviner comme les parties les plus vitales de la fonction. Quant à quelle fonction fait le pire ou le meilleur? Le graphique parle de lui-même.
Avec cela réglé, voici les graphiques.
Hashables non ordonnés
(Zoomé)
Hashables commandés
(Zoomé)
Unhashables commandés
(Zoomé)
la source
J'avais un dict dans ma liste, donc je ne pouvais pas utiliser l'approche ci-dessus. J'ai eu l'erreur:
Donc, si vous vous souciez de la commande et / ou que certains articles ne sont pas lavables . Ensuite, vous pourriez trouver cela utile:
Certains peuvent considérer que la compréhension de la liste avec un effet secondaire n'est pas une bonne solution. Voici une alternative:
la source
map
avec un effet secondaire est encore plus trompeur qu'un listcomp avec un effet secondaire. En outre,lambda x: unique_list.append(x)
c'est juste un moyen plus maladroit et plus lent de passerunique_list.append
.Toutes les approches préservant l'ordre que j'ai vues jusqu'ici utilisent soit une comparaison naïve (avec O (n ^ 2) complexité temporelle au mieux) ou des combinaisons lourdes
OrderedDicts
/set
+list
qui sont limitées aux entrées lavables. Voici une solution O (nlogn) indépendante du hachage:La mise à jour a ajouté l'
key
argument, la documentation et la compatibilité Python 3.la source
tuple()
et de les hacher. | | | | - D'une manière générale, le processus de hachage prend un temps proportionnel à la taille de l'ensemble des données, tandis que cette solution prend un temps O (nlog (n)), dépendant uniquement de la longueur de la liste.reduce()
travaille déjà sur une collection triéesrt_enum
, pourquoi avez-vous postulé àsorted
nouveau?Si vous souhaitez conserver l'ordre et ne pas utiliser de modules externes, voici un moyen simple de le faire:
Remarque: Cette méthode préserve l'ordre d'apparition, donc, comme indiqué ci-dessus, neuf viendront après un car c'était la première fois qu'elle apparaissait. Cependant, c'est le même résultat que vous obtiendriez en faisant
mais il est beaucoup plus court et tourne plus vite.
Cela fonctionne car chaque fois que la
fromkeys
fonction essaie de créer une nouvelle clé, si la valeur existe déjà, elle la remplace simplement. Cependant, cela n'affectera pas du tout le dictionnaire, carfromkeys
crée un dictionnaire où toutes les clés ont la valeurNone
, donc il élimine efficacement tous les doublons de cette façon.la source
Vous pouvez également faire ceci:
La raison pour laquelle cela fonctionne est que cette
index
méthode ne renvoie que le premier index d'un élément. Les éléments en double ont des indices plus élevés. Reportez-vous ici :la source
list.index
est une opération en temps linéaire, ce qui rend votre solution quadratique.Essayez d'utiliser des ensembles:
la source
Réduisez la variante en conservant la commande:
Supposons que nous ayons une liste:
Réduire la variante (inefficace):
5 fois plus rapide mais plus sophistiqué
Explication:
la source
La meilleure approche pour supprimer les doublons d'une liste est d'utiliser la fonction set () , disponible en python, convertissant à nouveau cet ensemble en liste
la source
Vous pouvez utiliser la fonction suivante:
Exemple :
Usage:
['ceci', 'est', 'un', 'liste', 'avec', 'duplique', 'dans', 'le']
la source
Il existe de nombreuses autres réponses suggérant différentes façons de le faire, mais ce sont toutes des opérations par lots, et certaines d'entre elles jettent la commande d'origine. Cela peut convenir selon ce dont vous avez besoin, mais si vous souhaitez parcourir les valeurs dans l'ordre de la première instance de chaque valeur et que vous souhaitez supprimer les doublons à la volée par rapport à tous à la fois, vous pouvez utiliser ce générateur:
Cela renvoie un générateur / itérateur, vous pouvez donc l'utiliser n'importe où que vous pouvez utiliser un itérateur.
Production:
Si vous en voulez un
list
, vous pouvez le faire:Production:
la source
seen = set(iterable); for item in seen: yield item
est presque certainement plus rapide. (Je n'ai pas essayé ce cas spécifique, mais ce serait ma supposition.)Sans utiliser l'ensemble
la source
Vous pouvez utiliser
set
pour supprimer les doublons:Mais notez que les résultats ne seront pas ordonnés. Si c'est un problème:
la source
Une meilleure approche pourrait être,
et l'ordre reste préservé.
la source
Celui-ci se soucie de la commande sans trop de tracas (OrderdDict & autres). Probablement pas le moyen le plus Pythonique, ni le plus court, mais fait l'affaire:
la source
list
); 2. Votre méthode est extrêmement mauvaise: elle est quadratique en nombre d'élémentslist
.le code ci-dessous est simple pour supprimer les doublons dans la liste
il renvoie [1,2,3,4]
la source
list(set(..))
(plus d'un million de passes) battra cette solution d'environ 10 secondes entières - alors que cette approche prend environ 12 secondes,list(set(..))
ne prend qu'environ 2 secondes!Voici la solution pythonique la plus rapide comparée à d'autres répertoriées dans les réponses.
L'utilisation des détails d'implémentation de l'évaluation des courts-circuits permet d'utiliser la compréhension de liste, ce qui est assez rapide.
visited.add(item)
renvoie toujoursNone
comme résultat, qui est évalué commeFalse
, donc le côté droit deor
serait toujours le résultat d'une telle expression.Faites le temps vous-même
la source
Utilisation de l' ensemble :
En utilisant unique :
la source
Malheureusement. La plupart des réponses ici ne préservent pas l'ordre ou sont trop longues. Voici une réponse simple et préservant l'ordre.
Cela vous donnera x avec les doublons supprimés mais préservant l'ordre.
la source
Manière très simple en Python 3:
la source
sorted(list(...))
est redondant (sorted
convertit déjà implicitement son argument en un nouveaulist
, le trie, puis renvoie le nouveaulist
, donc utiliser les deux signifie créer un temporaire inutilelist
). Utilisez uniquementlist
si le résultat n'a pas besoin d'être trié, utilisez uniquementsorted
si le résultat doit être trié.La magie de Python Type intégré
En python, il est très facile de traiter les cas compliqués comme celui-ci et uniquement par le type intégré de python.
Laissez-moi vous montrer comment faire!
Méthode 1: Cas général
La façon ( code 1 ligne ) de supprimer l'élément dupliqué dans la liste et de conserver l'ordre de tri
Vous obtiendrez le résultat
Méthode 2: cas spécial
Le cas particulier pour traiter les données non partageables ( codes à 3 lignes )
Vous obtiendrez le résultat:
Parce que le tuple est lavable et vous pouvez facilement convertir des données entre la liste et le tuple
la source