Suppression des doublons dans les listes
à peu près j'ai besoin d'écrire un programme pour vérifier si une liste a 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
30 réponses
L'approche commune pour obtenir une collection unique d'objets est d'utiliser un set
. Les ensembles sont unordered collections de objets distincts . Pour créer un ensemble à partir de n'importe quel itérable, vous pouvez simplement le passer à la fonction intégrée set()
. Si vous avez besoin plus tard d'une liste réelle à nouveau, vous pouvez également passer l'ensemble à la fonction list()
.
L'exemple suivant devrait couvrir ce que vous essayez de faire:
>>> t = [1, 2, 3, 1, 2, 5, 6, 7, 8]
>>> t
[1, 2, 3, 1, 2, 5, 6, 7, 8]
>>> list(set(t))
[1, 2, 3, 5, 6, 7, 8]
>>> s = [1, 2, 3]
>>> list(set(t) - set(s))
[8, 5, 6, 7]
Comme vous pouvez le voir dans l'exemple, la commande d'origine ne l'est pas. Comme mentionné ci-dessus, les ensembles eux-mêmes sont des collections non ordonnées, de sorte que l'ordre est perdu. Lors de la conversion d'un retour à une liste, un ordre arbitraire est créé.
Si l'ordre est important pour vous, alors vous devrez utiliser un autre mécanisme. Une solution très commune pour cela est s'appuyer sur OrderedDict
pour conserver l'ordre des touches lors de l'insertion:
>>> from collections import OrderedDict
>>> list(OrderedDict.fromkeys(t))
[1, 2, 3, 5, 6, 7, 8]
notez qu'il s'agit de créer d'abord un dictionnaire, puis une liste à partir de celui-ci. Donc, si vous n'avez pas réellement besoin de préserver l'ordre, il est préférable d'utiliser un ensemble. Cochez cette question pour plus de détails et d'autres façons de préserver l'ordre lors de la suppression des doublons.
enfin, notez que tant la solution set
que la solution OrderedDict
exigent que vos articles soient hachable . Cela signifie généralement qu'ils ont d'être immuable. Si vous avez à traiter avec des éléments qui ne sont pas hachables (par exemple des objets list), alors vous devrez utiliser une approche lente dans laquelle vous devrez essentiellement comparer chaque élément avec chaque autre élément dans une boucle imbriquée.
en Python 2.7 , la nouvelle façon de supprimer les doublons d'un itérable tout en le gardant dans l'ordre original est:
>>> from collections import OrderedDict
>>> list(OrderedDict.fromkeys('abracadabra'))
['a', 'b', 'r', 'c', 'd']
en Python 3.5 , l'OrderedDict a une implémentation C. Mes timings 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 commandé 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 le plus rapide de deduping tout en conservant l'ordre:
>>> list(dict.fromkeys('abracadabra'))
['a', 'b', 'r', 'c', 'd']
en Python 3.7 , le dict régulier est garanti aux deux commandé à travers toutes les implémentations. ainsi, la solution la plus courte et la plus rapide est:
>>> list(dict.fromkeys('abracadabra'))
['a', 'b', 'r', 'c', 'd']
C'est un one-liner: list(set(source_list))
fera l'affaire.
A set
est quelque chose qui ne peut pas avoir de doublons.
mise à Jour: une ordonnance de préservation de la démarche est de deux lignes:
from collections import OrderedDict
OrderedDict((x, True) for x in source_list).keys()
ici nous utilisons le fait que OrderedDict
se souvient de l'ordre d'insertion des clés, et ne le change pas quand une valeur à une clé particulière est mise à jour. Nous insérons True
comme valeurs, mais nous pourrions insérer n'importe quoi, valeurs sont tout simplement pas utilisé. ( set
fonctionne beaucoup comme un dict
avec des valeurs ignorées, aussi.)
>>> t = [1, 2, 3, 1, 2, 5, 6, 7, 8]
>>> t
[1, 2, 3, 1, 2, 5, 6, 7, 8]
>>> s = []
>>> for i in t:
if i not in s:
s.append(i)
>>> s
[1, 2, 3, 5, 6, 7, 8]
si vous ne vous souciez pas de l'ordre, faites juste ceci:
def remove_duplicates(l):
return list(set(l))
Un set
est la garantie de ne pas avoir de doublons.
pour faire une nouvelle liste 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]
puis newlist
sera [1,2,3,4,5]
ceci vérifie que chaque nouvel élément n'est pas déjà apparu dans la liste avant de l'ajouter. Il n'a pas non plus besoin d'importations.
une autre façon de faire:
>>> seq = [1,2,3,'a', 'a', 1,2]
>> dict.fromkeys(seq).keys()
['a', 1, 2, 3]
un collègue m'a envoyé aujourd'hui la réponse acceptée comme faisant partie de son code pour une entrevue. 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)
def ordered_set(in_list):
out_list = []
added = set()
for val in in_list:
if not val in added:
out_list.append(val)
added.add(val)
return out_list
pour comparer l'efficacité, j'ai utilisé un échantillon aléatoire de 100 entiers - 62 étaient uniques
from random import randint
x = [randint(0,100) for _ in xrange(100)]
In [131]: len(set(x))
Out[131]: 62
Voici les résultats des mesures
In [129]: %timeit list(OrderedDict.fromkeys(x))
10000 loops, best of 3: 86.4 us per loop
In [130]: %timeit ordered_set(x)
100000 loops, best of 3: 15.1 us per loop
que se passe-t-il si set est retiré de la solution?
def ordered_set(inlist):
out_list = []
for val in inlist:
if not val in out_list:
out_list.append(val)
return out_list
le résultat n'est pas aussi mauvais qu'avec le OrderedDict , mais encore plus de 3 fois de la solution originale
In [136]: %timeit ordered_set(x)
10000 loops, best of 3: 52.6 us per loop
il y a aussi des solutions utilisant Pandas et Numpy. Ils reviennent tableau numpy, donc vous devez utiliser la fonction .tolist()
si vous voulez une liste.
t=['a','a','b','b','b','c','c','c']
t2= ['c','c','b','b','b','a','a','a']
Pandas solution
utilisant la fonction Pandas unique()
:
import pandas as pd
pd.unique(t).tolist()
>>>['a','b','c']
pd.unique(t2).tolist()
>>>['c','b','a']
Numpy solution
utilisant la fonction numpy unique()
.
import numpy as np
np.unique(t).tolist()
>>>['a','b','c']
np.unique(t2).tolist()
>>>['a','b','c']
notez que numpy.unique () trie également les valeurs . Ainsi la liste t2
est retournée triée. Si vous voulez que l'ordre soit préservé, utilisez comme dans cette réponse :
_, idx = np.unique(t2, return_index=True)
t2[np.sort(idx)].tolist()
>>>['c','b','a']
la solution n'est pas aussi élégante que les 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é.
Simple et facile:
myList = [1, 2, 3, 1, 2, 5, 6, 7, 8]
cleanlist = []
[cleanlist.append(x) for x in myList if x not in cleanlist]
sortie:
>>> cleanlist
[1, 2, 3, 5, 6, 7, 8]
j'ai eu un dict dans ma liste, donc je ne pouvais pas utiliser l'approche décrite ci-dessus. J'ai eu l'erreur:
TypeError: unhashable type:
donc si vous vous souciez de commander et/ou certains articles sont unhashable . Alors vous pourriez trouver cela utile:
def make_unique(original_list):
unique_list = []
[unique_list.append(obj) for obj in original_list if obj not in unique_list]
return unique_list
certains peuvent considérer que la compréhension de la liste avec un effet secondaire n'est pas une bonne solution. Voici une alternative:
def make_unique(original_list):
unique_list = []
map(lambda x: unique_list.append(x) if (x not in unique_list) else False, original_list)
return unique_list
Essayez d'utiliser des jeux:
import sets
t = sets.Set(['a', 'b', 'c', 'd'])
t1 = sets.Set(['a', 'b', 'c'])
print t | t1
print t - t1
vous pourriez aussi faire ceci:
>>> t = [1, 2, 3, 3, 2, 4, 5, 6]
>>> s = [x for i, x in enumerate(t) if i == t.index(x)]
>>> s
[1, 2, 3, 4, 5, 6]
la raison pour laquelle ci-dessus fonctionne est que la méthode index
retourne seulement le premier index d'un élément. Les éléments dupliqués ont des indices plus élevés. Se référer à ici :
liste.indice (x [, début [, fin]])
Retour index à base zéro dans la liste de le premier article dont la valeur est X. Soulève une erreur de valeur si là n' un tel objet.
toutes les approches de conservation des commandes que j'ai vu jusqu'ici soit utiliser la comparaison naïve (avec O (N^2) le temps-la complexité au mieux) ou lourd-poids OrderedDicts
/ set
+ list
les combinaisons qui sont limitées aux entrées hachables. Voici une solution o(nlogn) indépendante du hachage:
Update a ajouté l'argument key
, la documentation et la compatibilité Python 3.
# from functools import reduce <-- add this import on Python 3
def uniq(iterable, key=lambda x: x):
"""
Remove duplicates from an iterable. Preserves order.
:type iterable: Iterable[Ord => A]
:param iterable: an iterable of objects of any orderable type
:type key: Callable[A] -> (Ord => B)
:param key: optional argument; by default an item (A) is discarded
if another item (B), such that A == B, has already been encountered and taken.
If you provide a key, this condition changes to key(A) == key(B); the callable
must return orderable objects.
"""
# Enumerate the list to restore order lately; reduce the sorted list; restore order
def append_unique(acc, item):
return acc if key(acc[-1][1]) == key(item[1]) else acc.append(item) or acc
srt_enum = sorted(enumerate(iterable), key=lambda item: key(item[1]))
return [item[1] for item in sorted(reduce(append_unique, srt_enum, [srt_enum[0]]))]
la meilleure façon de supprimer les doublons d'une liste est d'utiliser la fonction set() , disponible en python, convertissant à nouveau ce set en liste
In [2]: some_list = ['a','a','v','v','v','c','c','d']
In [3]: list(set(some_list))
Out[3]: ['a', 'c', 'd', 'v']
celui-ci se soucie de l'ordre sans trop de tracas (OrderdDict & autres). Probablement pas la voie la plus pythonique, ni la plus courte, mais fait le tour:
def remove_duplicates(list):
''' Removes duplicate items from a list '''
singles_list = []
for element in list:
if element not in singles_list:
singles_list.append(element)
return singles_list
réduire la variante avec conserver la commande:
supposons que nous avons la liste:
l = [5, 6, 6, 1, 1, 2, 2, 3, 4]
réduire la variante (inefficace):
>>> reduce(lambda r, v: v in r and r or r + [v], l, [])
[5, 6, 1, 2, 3, 4]
5 x plus rapide mais plus sophistiqué
>>> reduce(lambda r, v: v in r[1] and r or (r[0].append(v) or r[1].add(v)) or r, l, ([], set()))[0]
[5, 6, 1, 2, 3, 4]
explication:
default = (list(), set())
# user list to keep order
# use set to make lookup faster
def reducer(result, item):
if item not in result[1]:
result[0].append(item)
result[1].add(item)
return result
reduce(reducer, l, default)[0]
le code ci-dessous est simple pour supprimer le double dans la liste
def remove_duplicates(x):
a = []
for i in x:
if i not in a:
a.append(i)
return a
print remove_duplicates([1,2,2,3,3,4])
il renvoie [1,2,3,4]
il y a beaucoup d'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 l'ordre original. Cela peut être correct en fonction de ce dont vous avez besoin, mais si vous voulez itérer au-dessus des valeurs dans l'ordre de la première instance de chaque valeur, et vous voulez supprimer les doublons à la volée versus tout à la fois, vous pouvez utiliser ce générateur:
def uniqify(iterable):
seen = set()
for item in iterable:
if item not in seen:
seen.add(item)
yield item
renvoie un générateur / itérateur, vous pouvez donc l'utiliser partout où vous pouvez utiliser un itérateur.
for unique_item in uniqify([1, 2, 3, 4, 3, 2, 4, 5, 6, 7, 6, 8, 8]):
print(unique_item, end=' ')
print()
sortie:
1 2 3 4 5 6 7 8
si vous voulez un list
, vous pouvez le faire:
unique_list = list(uniqify([1, 2, 3, 4, 3, 2, 4, 5, 6, 7, 6, 8, 8]))
print(unique_list)
sortie:
[1, 2, 3, 4, 5, 6, 7, 8]
sans utiliser " set
data=[1, 2, 3, 1, 2, 5, 6, 7, 8]
uni_data=[]
for dat in data:
if dat not in uni_data:
uni_data.append(dat)
print(uni_data)
Voici la solution pythonique la plus rapide pour les autres.
L'utilisation des détails de mise en œuvre de l'évaluation de court-circuit permet d'utiliser la compréhension de liste, qui est assez rapide. visited.add(item)
renvoie toujours None
, ce qui est évalué comme False
, de sorte que le côté droit de or
serait toujours le résultat d'une telle expression.
Temps-le vous-même
def deduplicate(sequence):
visited = set()
adder = visited.add # get rid of qualification overhead
out = [adder(item) or item for item in sequence if item not in visited]
return out
utilisant set :
a = [0,1,2,3,4,3,3,4]
a = list(set(a))
print a
à l'Aide uniques :
import numpy as np
a = [0,1,2,3,4,3,3,4]
a = np.unique(a).tolist()
print a
façon très simple en Python 3:
>>> n = [1, 2, 3, 4, 1, 1]
>>> n
[1, 2, 3, 4, 1, 1]
>>> m = sorted(list(set(n)))
>>> m
[1, 2, 3, 4]
de nos jours, vous pouvez utiliser la classe de comptoir:
>>> import collections
>>> c = collections.Counter([1, 2, 3, 4, 5, 6, 1, 1, 1, 1])
>>> c.keys()
dict_keys([1, 2, 3, 4, 5, 6])
voici un exemple, Liste de retour sans répétitions préserver l'ordre. N'a pas besoin de ces importations.
def GetListWithoutRepetitions(loInput):
# return list, consisting of elements of list/tuple loInput, without repetitions.
# Example: GetListWithoutRepetitions([None,None,1,1,2,2,3,3,3])
# Returns: [None, 1, 2, 3]
if loInput==[]:
return []
loOutput = []
if loInput[0] is None:
oGroupElement=1
else: # loInput[0]<>None
oGroupElement=None
for oElement in loInput:
if oElement<>oGroupElement:
loOutput.append(oElement)
oGroupElement = oElement
return loOutput
Cochez cette case si vous voulez supprimer les doublons (modifier en place plutôt que de retourner une nouvelle liste) sans utiliser Inbuilt set, dict.clés, uniqify, compteur
>>> t = [1, 2, 3, 1, 2, 5, 6, 7, 8]
>>> for i in t:
... if i in t[t.index(i)+1:]:
... t.remove(i)
...
>>> t
[3, 1, 2, 5, 6, 7, 8]
pour supprimer les doublons, faites-en un ensemble et ensuite faites-en une liste et imprimez/utilisez-la. Un ensemble est garanti d'avoir des éléments uniques. Par exemple:
a = [1,2,3,4,5,9,11,15]
b = [4,5,6,7,8]
c=a+b
print c
print list(set(c)) #one line for getting unique elements of c
la sortie sera la suivante (cochée en python 2.7)
[1, 2, 3, 4, 5, 9, 11, 15, 4, 5, 6, 7, 8] #simple list addition with duplicates
[1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 15] #duplicates removed!!
vous pouvez faire cela simplement en utilisant des ensembles.
etape n ° 1: Obtenir les Différents éléments des listes
Step2 Obtenir les éléments Communs des listes
Etape 3 Combiner
In [1]: a = ["apples", "bananas", "cucumbers"]
In [2]: b = ["pears", "apples", "watermelons"]
In [3]: set(a).symmetric_difference(b).union(set(a).intersection(b))
Out[3]: {'apples', 'bananas', 'cucumbers', 'pears', 'watermelons'}
def remove_duplicates(A):
[A.pop(count) for count,elem in enumerate(A) if A.count(elem)!=1]
return A
Une liste comprehesion de supprimer les doublons