valor una saber repetidos repetido ocurrencias numeros lista identificar esta encontrar eliminar elementos elemento duplicados contar python string list duplicates

python - saber - ¿Cómo puedo verificar si hay duplicados en una lista plana?



saber si un elemento esta en una lista python (6)

Esto es viejo, pero las respuestas aquí me llevaron a una solución ligeramente diferente. Si está dispuesto a abusar de las comprensiones, puede sufrir un cortocircuito de esta manera.

xs = [1, 2, 1] s = set() any(x in s or s.add(x) for x in xs) # You can use a similar approach to actually retrieve the duplicates. s = set() duplicates = set(x for x in xs if x in s or s.add(x))

Por ejemplo, dada la lista [''one'', ''two'', ''one''] , el algoritmo debería devolver True , mientras que dado [''one'', ''two'', ''three''] debería devolver False .


Hace poco respondí una pregunta relacionada para establecer todos los duplicados en una lista, usando un generador. Tiene la ventaja de que si se usa solo para establecer "si hay un duplicado", entonces solo necesita obtener el primer elemento y el resto se puede ignorar, que es el atajo definitivo.

Este es un enfoque basado en un conjunto interesante que moooeeeep directamente de moooeeeep :

def getDupes(l): seen = set() seen_add = seen.add for x in l: if x in seen or seen_add(x): yield x

En consecuencia, una lista completa de incautos sería una list(getDupes(etc)) . Para simplemente probar "si" hay un duplicado, debe ser envuelto de la siguiente manera:

def hasDupes(l): try: if getDupes(c).next(): return True # Found a dupe except StopIteration: pass return False

Esto se escala bien y proporciona tiempos de operación consistentes dondequiera que el dupe esté en la lista - Probé con listas de hasta 1m de entradas. Si sabes algo sobre los datos, específicamente, que los engañados probablemente aparezcan en la primera mitad, u otras cosas que te permitan desvirtuar tus necesidades, como la necesidad de obtener los verdaderos engañadores, entonces hay un par de localizadores de engaños realmente alternativos. eso podría superar. Los dos que recomiendo son ...

Enfoque basado en dict simple, muy legible:

def getDupes(c): d = {} for i in c: if i in d: if d[i]: yield i d[i] = False else: d[i] = True

Aproveche los itertools (esencialmente un ifilter / izip / tee) en la lista ordenada, muy eficiente si obtiene todos los dupes aunque no tan rápido como para obtener el primero:

def getDupes(c): a, b = itertools.tee(sorted(c)) next(b, None) r = None for k, g in itertools.ifilter(lambda x: x[0]==x[1], itertools.izip(a, b)): if k != r: yield k r = k

Estos fueron los mejores ejecutores de los enfoques que probé para la lista completa , con el primer engaño en cualquier lugar en una lista de elementos de 1 m desde el principio hasta el centro. Era sorprendente lo poco que sobrecargaba el paso de clasificación. Su kilometraje puede variar, pero aquí están mis resultados cronometrados específicos:

Finding FIRST duplicate, single dupe places "n" elements in to 1m element array Test set len change : 50 - . . . . . -- 0.002 Test in dict : 50 - . . . . . -- 0.002 Test in set : 50 - . . . . . -- 0.002 Test sort/adjacent : 50 - . . . . . -- 0.023 Test sort/groupby : 50 - . . . . . -- 0.026 Test sort/zip : 50 - . . . . . -- 1.102 Test sort/izip : 50 - . . . . . -- 0.035 Test sort/tee/izip : 50 - . . . . . -- 0.024 Test moooeeeep : 50 - . . . . . -- 0.001 * Test iter*/sorted : 50 - . . . . . -- 0.027 Test set len change : 5000 - . . . . . -- 0.017 Test in dict : 5000 - . . . . . -- 0.003 * Test in set : 5000 - . . . . . -- 0.004 Test sort/adjacent : 5000 - . . . . . -- 0.031 Test sort/groupby : 5000 - . . . . . -- 0.035 Test sort/zip : 5000 - . . . . . -- 1.080 Test sort/izip : 5000 - . . . . . -- 0.043 Test sort/tee/izip : 5000 - . . . . . -- 0.031 Test moooeeeep : 5000 - . . . . . -- 0.003 * Test iter*/sorted : 5000 - . . . . . -- 0.031 Test set len change : 50000 - . . . . . -- 0.035 Test in dict : 50000 - . . . . . -- 0.023 Test in set : 50000 - . . . . . -- 0.023 Test sort/adjacent : 50000 - . . . . . -- 0.036 Test sort/groupby : 50000 - . . . . . -- 0.134 Test sort/zip : 50000 - . . . . . -- 1.121 Test sort/izip : 50000 - . . . . . -- 0.054 Test sort/tee/izip : 50000 - . . . . . -- 0.045 Test moooeeeep : 50000 - . . . . . -- 0.019 * Test iter*/sorted : 50000 - . . . . . -- 0.055 Test set len change : 500000 - . . . . . -- 0.249 Test in dict : 500000 - . . . . . -- 0.145 Test in set : 500000 - . . . . . -- 0.165 Test sort/adjacent : 500000 - . . . . . -- 0.139 Test sort/groupby : 500000 - . . . . . -- 1.138 Test sort/zip : 500000 - . . . . . -- 1.159 Test sort/izip : 500000 - . . . . . -- 0.126 Test sort/tee/izip : 500000 - . . . . . -- 0.120 * Test moooeeeep : 500000 - . . . . . -- 0.131 Test iter*/sorted : 500000 - . . . . . -- 0.157


Otra forma de hacerlo de manera sucinta es con Counter .

Para determinar si hay duplicados en la lista original:

from collections import Counter def has_dupes(l): return Counter(l).most_common()[0][0] > 1

O para obtener una lista de elementos que tienen duplicados:

def get_dupes(l): return [k for k, v in Counter(l).items() if v > 1]


Recomendado solo para listas cortas :

any(thelist.count(x) > 1 for x in thelist)

No lo use en una lista larga; puede llevar un tiempo proporcional al cuadrado de la cantidad de elementos en la lista.

Para listas más largas con elementos hashable (cadenas, números, & c):

def anydup(thelist): seen = set() for x in thelist: if x in seen: return True seen.add(x) return False

Si sus artículos no son lavables (sublistas, dicts, etc.) se vuelve más peludo, aunque aún es posible obtener O (N logN) si son al menos comparables. Pero necesita saber o probar las características de los artículos (hashable o no, comparables o no) para obtener el mejor rendimiento que pueda: O (N) para los hashables, O (N log N) para los elementos comparables que no se pueden procesar, de lo contrario se trata de O (N al cuadrado) y no hay nada que uno pueda hacer al respecto :-(.


Si le gusta el estilo de programación funcional, aquí hay una función útil, código auto-documentado y probado usando doctest .

def decompose(a_list): """Turns a list into a set of all elements and a set of duplicated elements. Returns a pair of sets. The first one contains elements that are found at least once in the list. The second one contains elements that appear more than once. >>> decompose([1,2,3,5,3,2,6]) (set([1, 2, 3, 5, 6]), set([2, 3])) """ return reduce( lambda (u, d), o : (u.union([o]), d.union(u.intersection([o]))), a_list, (set(), set())) if __name__ == "__main__": import doctest doctest.testmod()

Desde allí puede probar unicity comprobando si el segundo elemento del par devuelto está vacío:

def is_set(l): """Test if there is no duplicate element in l. >>> is_set([1,2,3]) True >>> is_set([1,2,1]) False >>> is_set([]) True """ return not decompose(l)[1]

Tenga en cuenta que esto no es eficiente ya que está construyendo explícitamente la descomposición. Pero a lo largo de la línea de usar reducir, puede llegar a algo equivalente (pero un poco menos eficiente) para responder 5:

def is_set(l): try: def func(s, o): if o in s: raise Exception return s.union([o]) reduce(func, l, set()) return True except: return False


Use set() para eliminar duplicados si todos los valores son manejables :

>>> your_list = [''one'', ''two'', ''one''] >>> len(your_list) != len(set(your_list)) True