¿Cómo encuentro los duplicados en una lista y creo otra lista con ellos?

¿Cómo puedo encontrar los duplicados en una lista de Python y crear otra lista de los duplicados? La lista solo contiene enteros.

Para eliminar duplicados utiliza set(a) . Para imprimir duplicados, algo como:

 a = [1,2,3,2,1,5,6,5,5,5] import collections print [item for item, count in collections.Counter(a).items() if count > 1] ## [1, 2, 5] 

Tenga en cuenta que el Counter no es particularmente eficiente ( tiempos ) y probablemente exagerar aquí. set se desempeñará mejor. Este código calcula una lista de elementos únicos en el orden de origen:

 seen = set() uniq = [] for x in a: if x not in seen: uniq.append(x) seen.add(x) 

o, más concisamente:

 seen = set() uniq = [x for x in a if x not in seen and not seen.add(x)] 

No recomiendo este último estilo, porque no es obvio lo que not seen.add(x) está haciendo (el método set add() siempre devuelve None , de ahí la necesidad de not ).

Para calcular la lista de elementos duplicados sin bibliotecas:

 seen = {} dupes = [] for x in a: if x not in seen: seen[x] = 1 else: if seen[x] == 1: dupes.append(x) seen[x] += 1 

Si los elementos de la lista no son hashables, no puede usar sets / dicts y tiene que recurrir a una solución de tiempo cuadrática (compare cada uno). Por ejemplo:

 a = [[1], [2], [3], [1], [5], [3]] no_dupes = [x for n, x in enumerate(a) if x not in a[:n]] print no_dupes # [[1], [2], [3], [5]] dupes = [x for n, x in enumerate(a) if x in a[:n]] print dupes # [[1], [3]] 
 >>> l = [1,2,3,4,4,5,5,6,1] >>> set([x for x in l if l.count(x) > 1]) set([1, 4, 5]) 

No necesita el recuento, solo si el elemento fue visto antes o no. Adapté esa respuesta a este problema:

 def list_duplicates(seq): seen = set() seen_add = seen.add # adds all elements it doesn't know yet to seen and all other to seen_twice seen_twice = set( x for x in seq if x in seen or seen_add(x) ) # turn the set into a list (as requested) return list( seen_twice ) a = [1,2,3,2,1,5,6,5,5,5] list_duplicates(a) # yields [1, 2, 5] 

Por si acaso la velocidad importa, aquí hay algunos horarios:

 # file: test.py import collections def thg435(l): return [x for x, y in collections.Counter(l).items() if y > 1] def moooeeeep(l): seen = set() seen_add = seen.add # adds all elements it doesn't know yet to seen and all other to seen_twice seen_twice = set( x for x in l if x in seen or seen_add(x) ) # turn the set into a list (as requested) return list( seen_twice ) def RiteshKumar(l): return list(set([x for x in l if l.count(x) > 1])) def JohnLaRooy(L): seen = set() seen2 = set() seen_add = seen.add seen2_add = seen2.add for item in L: if item in seen: seen2_add(item) else: seen_add(item) return list(seen2) l = [1,2,3,2,1,5,6,5,5,5]*100 

Aquí están los resultados: (¡bien hecho @JohnLaRooy!)

 $ python -mtimeit -s 'import test' 'test.JohnLaRooy(test.l)' 10000 loops, best of 3: 74.6 usec per loop $ python -mtimeit -s 'import test' 'test.moooeeeep(test.l)' 10000 loops, best of 3: 91.3 usec per loop $ python -mtimeit -s 'import test' 'test.thg435(test.l)' 1000 loops, best of 3: 266 usec per loop $ python -mtimeit -s 'import test' 'test.RiteshKumar(test.l)' 100 loops, best of 3: 8.35 msec per loop 

Curiosamente, además de los tiempos en sí, también la clasificación cambia ligeramente cuando se usa pypy. Lo más interesante es que el enfoque basado en el contador se beneficia enormemente de las optimizaciones de pypy, mientras que el método de almacenamiento en caché que he sugerido parece no tener casi ningún efecto.

 $ pypy -mtimeit -s 'import test' 'test.JohnLaRooy(test.l)' 100000 loops, best of 3: 17.8 usec per loop $ pypy -mtimeit -s 'import test' 'test.thg435(test.l)' 10000 loops, best of 3: 23 usec per loop $ pypy -mtimeit -s 'import test' 'test.moooeeeep(test.l)' 10000 loops, best of 3: 39.3 usec per loop 

Al parecer, este efecto está relacionado con la “duplicación” de los datos de entrada. He establecido l = [random.randrange(1000000) for i in xrange(10000)] y obtuve estos resultados:

 $ pypy -mtimeit -s 'import test' 'test.moooeeeep(test.l)' 1000 loops, best of 3: 495 usec per loop $ pypy -mtimeit -s 'import test' 'test.JohnLaRooy(test.l)' 1000 loops, best of 3: 499 usec per loop $ pypy -mtimeit -s 'import test' 'test.thg435(test.l)' 1000 loops, best of 3: 1.68 msec per loop 

Encontré esta pregunta mientras miraba algo relacionado, y me pregunto por qué nadie ofreció una solución basada en un generador. Resolver este problema sería:

 >>> print list(getDupes_9([1,2,3,2,1,5,6,5,5,5])) [1, 2, 5] 

Estaba preocupado por la escalabilidad, por lo que probé varios enfoques, incluidos elementos ingenuos que funcionan bien en listas pequeñas, pero su escala es horriblemente más grande (nota: habría sido mejor usar timeit, pero esto es ilustrativo).

Incluí @moooeeeep para comparación (es impresionantemente rápido: más rápido si la lista de entrada es completamente aleatoria) y un enfoque de itertools que es incluso más rápido nuevamente para la mayoría de las listas ordenadas … Ahora incluye el enfoque de pandas de @firelynx – lento, pero no horriblemente así, y simple. Nota: el enfoque de clasificación / tee / zip es consistentemente más rápido en mi máquina para grandes listas mayormente ordenadas, moooeeeep es más rápido para listas barajadas, pero su millaje puede variar.

Ventajas

  • muy rápido, simple de probar para cualquier duplicado usando el mismo código

Suposiciones

  • Los duplicados deben ser reportados una sola vez
  • El orden duplicado no necesita ser preservado
  • Duplicar podría estar en cualquier lugar en la lista

La solución más rápida, entradas de 1m:

 def getDupes(c): '''sort/tee/izip''' a, b = itertools.tee(sorted(c)) next(b, None) r = None for k, g in itertools.izip(a, b): if k != g: continue if k != r: yield k r = k 

Enfoques probados

 import itertools import time import random def getDupes_1(c): '''naive''' for i in xrange(0, len(c)): if c[i] in c[:i]: yield c[i] def getDupes_2(c): '''set len change''' s = set() for i in c: l = len(s) s.add(i) if len(s) == l: yield i def getDupes_3(c): '''in dict''' d = {} for i in c: if i in d: if d[i]: yield i d[i] = False else: d[i] = True def getDupes_4(c): '''in set''' s,r = set(),set() for i in c: if i not in s: s.add(i) elif i not in r: r.add(i) yield i def getDupes_5(c): '''sort/adjacent''' c = sorted(c) r = None for i in xrange(1, len(c)): if c[i] == c[i - 1]: if c[i] != r: yield c[i] r = c[i] def getDupes_6(c): '''sort/groupby''' def multiple(x): try: x.next() x.next() return True except: return False for k, g in itertools.ifilter(lambda x: multiple(x[1]), itertools.groupby(sorted(c))): yield k def getDupes_7(c): '''sort/zip''' c = sorted(c) r = None for k, g in zip(c[:-1],c[1:]): if k == g: if k != r: yield k r = k def getDupes_8(c): '''sort/izip''' c = sorted(c) r = None for k, g in itertools.izip(c[:-1],c[1:]): if k == g: if k != r: yield k r = k def getDupes_9(c): '''sort/tee/izip''' a, b = itertools.tee(sorted(c)) next(b, None) r = None for k, g in itertools.izip(a, b): if k != g: continue if k != r: yield k r = k def getDupes_a(l): '''moooeeeep''' seen = set() seen_add = seen.add # adds all elements it doesn't know yet to seen and all other to seen_twice for x in l: if x in seen or seen_add(x): yield x def getDupes_b(x): '''iter*/sorted''' x = sorted(x) def _matches(): for k,g in itertools.izip(x[:-1],x[1:]): if k == g: yield k for k, n in itertools.groupby(_matches()): yield k def getDupes_c(a): '''pandas''' import pandas as pd vc = pd.Series(a).value_counts() i = vc[vc > 1].index for _ in i: yield _ def hasDupes(fn,c): try: if fn(c).next(): return True # Found a dupe except StopIteration: pass return False def getDupes(fn,c): return list(fn(c)) STABLE = True if STABLE: print 'Finding FIRST then ALL duplicates, single dupe of "nth" placed element in 1m element array' else: print 'Finding FIRST then ALL duplicates, single dupe of "n" included in randomised 1m element array' for location in (50,250000,500000,750000,999999): for test in (getDupes_2, getDupes_3, getDupes_4, getDupes_5, getDupes_6, getDupes_8, getDupes_9, getDupes_a, getDupes_b, getDupes_c): print 'Test %-15s:%10d - '%(test.__doc__ or test.__name__,location), deltas = [] for FIRST in (True,False): for i in xrange(0, 5): c = range(0,1000000) if STABLE: c[0] = location else: c.append(location) random.shuffle(c) start = time.time() if FIRST: print '.' if location == test(c).next() else '!', else: print '.' if [location] == list(test(c)) else '!', deltas.append(time.time()-start) print ' -- %0.3f '%(sum(deltas)/len(deltas)), print print 

Los resultados para la prueba ‘Todos los duplicados’ fueron consistentes, encontrando “primero” duplicado luego “todos” duplicados en esta matriz:

 Finding FIRST then ALL duplicates, single dupe of "nth" placed element in 1m element array Test set len change : 500000 - . . . . . -- 0.264 . . . . . -- 0.402 Test in dict : 500000 - . . . . . -- 0.163 . . . . . -- 0.250 Test in set : 500000 - . . . . . -- 0.163 . . . . . -- 0.249 Test sort/adjacent : 500000 - . . . . . -- 0.159 . . . . . -- 0.229 Test sort/groupby : 500000 - . . . . . -- 0.860 . . . . . -- 1.286 Test sort/izip : 500000 - . . . . . -- 0.165 . . . . . -- 0.229 Test sort/tee/izip : 500000 - . . . . . -- 0.145 . . . . . -- 0.206 * Test moooeeeep : 500000 - . . . . . -- 0.149 . . . . . -- 0.232 Test iter*/sorted : 500000 - . . . . . -- 0.160 . . . . . -- 0.221 Test pandas : 500000 - . . . . . -- 0.493 . . . . . -- 0.499 

Cuando las listas se barajan primero, el precio de la clase se hace evidente: la eficiencia se reduce notablemente y el enfoque @moooeeeep domina, con los enfoques set y dict que son similares pero con menor rendimiento:

 Finding FIRST then ALL duplicates, single dupe of "n" included in randomised 1m element array Test set len change : 500000 - . . . . . -- 0.321 . . . . . -- 0.473 Test in dict : 500000 - . . . . . -- 0.285 . . . . . -- 0.360 Test in set : 500000 - . . . . . -- 0.309 . . . . . -- 0.365 Test sort/adjacent : 500000 - . . . . . -- 0.756 . . . . . -- 0.823 Test sort/groupby : 500000 - . . . . . -- 1.459 . . . . . -- 1.896 Test sort/izip : 500000 - . . . . . -- 0.786 . . . . . -- 0.845 Test sort/tee/izip : 500000 - . . . . . -- 0.743 . . . . . -- 0.804 Test moooeeeep : 500000 - . . . . . -- 0.234 . . . . . -- 0.311 * Test iter*/sorted : 500000 - . . . . . -- 0.776 . . . . . -- 0.840 Test pandas : 500000 - . . . . . -- 0.539 . . . . . -- 0.540 

Puedes usar iteration_utilities.duplicates :

 >>> from iteration_utilities import duplicates >>> list(duplicates([1,1,2,1,2,3,4,2])) [1, 1, 2, 2] 

o si solo desea uno de cada duplicado, se puede combinar con iteration_utilities.unique_everseen :

 >>> from iteration_utilities import unique_everseen >>> list(unique_everseen(duplicates([1,1,2,1,2,3,4,2]))) [1, 2] 

También puede manejar elementos inestables (sin embargo, a costa del rendimiento):

 >>> list(duplicates([[1], [2], [1], [3], [1]])) [[1], [1]] >>> list(unique_everseen(duplicates([[1], [2], [1], [3], [1]]))) [[1]] 

Eso es algo que solo algunos de los otros enfoques aquí pueden manejar.

Puntos de referencia

Hice un punto de referencia rápido que contiene la mayoría (pero no todos) de los enfoques mencionados aquí.

El primer punto de referencia incluyó solo un pequeño rango de longitudes de lista porque algunos enfoques tienen un comportamiento O(n**2) .

En los gráficos, el eje y representa el tiempo, por lo que un valor más bajo significa mejor. También se traza log-log para que se pueda visualizar mejor la amplia gama de valores:

introduzca la descripción de la imagen aquí

Eliminando los enfoques O(n**2) hice otro punto de referencia de hasta medio millón de elementos en una lista:

introduzca la descripción de la imagen aquí

Como puede ver, el enfoque unique_everseen(duplicates(...)) es más rápido que cualquiera de los otros enfoques e incluso el encadenamiento de unique_everseen(duplicates(...)) fue más rápido o igual de rápido que los otros enfoques.

Una cosa interesante adicional que se debe tener en cuenta aquí es que los enfoques de pandas son muy lentos para listas pequeñas, pero pueden competir fácilmente por listas más largas.

Sin embargo, como estos puntos de referencia muestran que la mayoría de los enfoques tienen un desempeño más o menos equitativo, no importa mucho cuál se use (a excepción de los 3 que tenían el tiempo de ejecución de O(n**2) ).

 from iteration_utilities import duplicates, unique_everseen from collections import Counter import pandas as pd import itertools def georg_counter(it): return [item for item, count in Counter(it).items() if count > 1] def georg_set(it): seen = set() uniq = [] for x in it: if x not in seen: uniq.append(x) seen.add(x) def georg_set2(it): seen = set() return [x for x in it if x not in seen and not seen.add(x)] def georg_set3(it): seen = {} dupes = [] for x in it: if x not in seen: seen[x] = 1 else: if seen[x] == 1: dupes.append(x) seen[x] += 1 def RiteshKumar_count(l): return set([x for x in l if l.count(x) > 1]) def moooeeeep(seq): seen = set() seen_add = seen.add # adds all elements it doesn't know yet to seen and all other to seen_twice seen_twice = set( x for x in seq if x in seen or seen_add(x) ) # turn the set into a list (as requested) return list( seen_twice ) def F1Rumors_implementation(c): a, b = itertools.tee(sorted(c)) next(b, None) r = None for k, g in zip(a, b): if k != g: continue if k != r: yield k r = k def F1Rumors(c): return list(F1Rumors_implementation(c)) def Edward(a): d = {} for elem in a: if elem in d: d[elem] += 1 else: d[elem] = 1 return [x for x, y in d.items() if y > 1] def wordsmith(a): return pd.Series(a)[pd.Series(a).duplicated()].values def NikhilPrabhu(li): li = li.copy() for x in set(li): li.remove(x) return list(set(li)) def firelynx(a): vc = pd.Series(a).value_counts() return vc[vc > 1].index.tolist() def HenryDev(myList): newList = set() for i in myList: if myList.count(i) >= 2: newList.add(i) return list(newList) def yota(number_lst): seen_set = set() duplicate_set = set(x for x in number_lst if x in seen_set or seen_set.add(x)) return seen_set - duplicate_set def IgorVishnevskiy(l): s=set(l) d=[] for x in l: if x in s: s.remove(x) else: d.append(x) return d def it_duplicates(l): return list(duplicates(l)) def it_unique_duplicates(l): return list(unique_everseen(duplicates(l))) 

Punto de referencia 1

 from simple_benchmark import benchmark import random funcs = [ georg_counter, georg_set, georg_set2, georg_set3, RiteshKumar_count, moooeeeep, F1Rumors, Edward, wordsmith, NikhilPrabhu, firelynx, HenryDev, yota, IgorVishnevskiy, it_duplicates, it_unique_duplicates ] args = {2**i: [random.randint(0, 2**(i-1)) for _ in range(2**i)] for i in range(2, 12)} b = benchmark(funcs, args, 'list size') b.plot() 

Punto de referencia 2

 funcs = [ georg_counter, georg_set, georg_set2, georg_set3, moooeeeep, F1Rumors, Edward, wordsmith, firelynx, yota, IgorVishnevskiy, it_duplicates, it_unique_duplicates ] args = {2**i: [random.randint(0, 2**(i-1)) for _ in range(2**i)] for i in range(2, 20)} b = benchmark(funcs, args, 'list size') b.plot() 

Renuncia

1 Esto es de una biblioteca de terceros que he escrito: iteration_utilities .

colecciones.Counter es nuevo en Python 2.7:

 Python 2.5.4 (r254:67916, May 31 2010, 15:03:39) [GCC 4.1.2 20080704 (Red Hat 4.1.2-46)] on linux2 a = [1,2,3,2,1,5,6,5,5,5] import collections print [x for x, y in collections.Counter(a).items() if y > 1] Type "help", "copyright", "credits" or "license" for more information. File "", line 1, in AttributeError: 'module' object has no attribute 'Counter' >>> 

En una versión anterior puedes usar un dict convencional en su lugar:

 a = [1,2,3,2,1,5,6,5,5,5] d = {} for elem in a: if elem in d: d[elem] += 1 else: d[elem] = 1 print [x for x, y in d.items() if y > 1] 

Utilizando pandas:

 >>> import pandas as pd >>> a = [1, 2, 1, 3, 3, 3, 0] >>> pd.Series(a)[pd.Series(a).duplicated()].values array([1, 3, 3]) 

Aquí hay una solución limpia y concisa:

 for x in set(li): li.remove(x) li = list(set(li)) 

¿Qué tal si recorre cada elemento de la lista verificando el número de ocurrencias y luego agregándolas a un conjunto que luego imprimirá los duplicados? Espero que esto ayude a alguien por ahí.

 myList = [2 ,4 , 6, 8, 4, 6, 12]; newList = set() for i in myList: if myList.count(i) >= 2: newList.add(i) print(list(newList)) ## [4 , 6] 

Sin convertir a la lista y probablemente la forma más sencilla sería algo como a continuación. Esto puede ser útil durante una entrevista cuando piden no usar sets

 a=[1,2,3,3,3] dup=[] for each in a: if each not in dup: dup.append(each) print(dup) 

======= else para obtener 2 listas separadas de valores únicos y valores duplicados

 a=[1,2,3,3,3] uniques=[] dups=[] for each in a: if each not in uniques: uniques.append(each) else: dups.append(each) print("Unique values are below:") print(uniques) print("Duplicate values are below:") print(dups) 

Haría esto con pandas, porque uso mucho pandas

 import pandas as pd a = [1,2,3,3,3,4,5,6,6,7] vc = pd.Series(a).value_counts() vc[vc > 1].index.tolist() 

Da

 [3,6] 

Probablemente no sea muy eficiente, pero seguro que es menos código que muchas de las otras respuestas, así que pensé que contribuiría

El tercer ejemplo de la respuesta aceptada da una respuesta errónea y no intenta dar duplicados. Aquí está la versión correcta:

 number_lst = [1, 1, 2, 3, 5, ...] seen_set = set() duplicate_set = set(x for x in number_lst if x in seen_set or seen_set.add(x)) unique_set = seen_set - duplicate_set 

Un poco tarde, pero tal vez útil para algunos. Para una lista bastante larga, encontré que esto funcionó para mí.

 l=[1,2,3,5,4,1,3,1] s=set(l) d=[] for x in l: if x in s: s.remove(x) else: d.append(x) d [1,3,1] 

Muestra justo y todos los duplicados y conserva el orden.

Una forma muy simple y rápida de encontrar duplicados con una iteración en Python es:

 testList = ['red', 'blue', 'red', 'green', 'blue', 'blue'] testListDict = {} for item in testList: try: testListDict[item] += 1 except: testListDict[item] = 1 print testListDict 

La salida será la siguiente:

 >>> print testListDict {'blue': 3, 'green': 1, 'red': 2} 

Esto y más en mi blog http://www.howtoprogramwithpython.com

Podemos usar itertools.groupby para encontrar todos los elementos que tienen dups:

 from itertools import groupby myList = [2, 4, 6, 8, 4, 6, 12] # when the list is sorted, groupby groups by consecutive elements which are similar for x, y in groupby(sorted(myList)): # list(y) returns all the occurences of item x if len(list(y)) > 1: print x 

La salida será:

 4 6 
 list2 = [1, 2, 3, 4, 1, 2, 3] lset = set() [(lset.add(item), list2.append(item)) for item in list2 if item not in lset] print list(lset) 

Una solución de línea:

 set([i for i in list if sum([1 for a in list if a == i]) > 1]) 

Hay muchas respuestas aquí arriba, pero creo que este es un enfoque relativamente legible y fácil de entender:

 def get_duplicates(sorted_list): duplicates = [] last = sorted_list[0] for x in sorted_list[1:]: if x == last: duplicates.append(x) last = x return set(duplicates) 

Notas:

  • Si desea conservar el recuento de duplicados, elimine la conversión para ‘establecer’ en la parte inferior para obtener la lista completa
  • Si prefiere usar generadores, reemplace duplicates.append (x) con el rendimiento x y la statement de devolución en la parte inferior (puede realizar la conversión para establecer más adelante)

Aquí hay un generador rápido que usa un dict para almacenar cada elemento como una clave con un valor booleano para verificar si el elemento duplicado ya se ha producido.

Para listas con todos los elementos que son tipos hashable:

 def gen_dupes(array): unique = {} for value in array: if value in unique and unique[value]: unique[value] = False yield value else: unique[value] = True array = [1, 2, 2, 3, 4, 1, 5, 2, 6, 6] print(list(gen_dupes(array))) # => [2, 1, 6] 

Para listas que pueden contener listas:

 def gen_dupes(array): unique = {} for value in array: is_list = False if type(value) is list: value = tuple(value) is_list = True if value in unique and unique[value]: unique[value] = False if is_list: value = list(value) yield value else: unique[value] = True array = [1, 2, 2, [1, 2], 3, 4, [1, 2], 5, 2, 6, 6] print(list(gen_dupes(array))) # => [2, [1, 2], 6] 
 def removeduplicates(a): seen = set() for i in a: if i not in seen: seen.add(i) return seen print(removeduplicates([1,1,2,2])) 

Algunas otras pruebas. Por supuesto que hacer …

 set([x for x in l if l.count(x) > 1]) 

… es demasiado costoso Es aproximadamente 500 veces más rápido (la matriz más larga da mejores resultados) para usar el siguiente método final:

 def dups_count_dict(l): d = {} for item in l: if item not in d: d[item] = 0 d[item] += 1 result_d = {key: val for key, val in d.iteritems() if val > 1} return result_d.keys() 

Solo 2 bucles, no hay operaciones l.count() muy costosas.

Aquí hay un código para comparar los métodos por ejemplo. El código está abajo, aquí está la salida:

 dups_count: 13.368s # this is a function which uses l.count() dups_count_dict: 0.014s # this is a final best function (of the 3 functions) dups_count_counter: 0.024s # collections.Counter 

El código de prueba:

 import numpy as np from time import time from collections import Counter class TimerCounter(object): def __init__(self): self._time_sum = 0 def start(self): self.time = time() def stop(self): self._time_sum += time() - self.time def get_time_sum(self): return self._time_sum def dups_count(l): return set([x for x in l if l.count(x) > 1]) def dups_count_dict(l): d = {} for item in l: if item not in d: d[item] = 0 d[item] += 1 result_d = {key: val for key, val in d.iteritems() if val > 1} return result_d.keys() def dups_counter(l): counter = Counter(l) result_d = {key: val for key, val in counter.iteritems() if val > 1} return result_d.keys() def gen_array(): np.random.seed(17) return list(np.random.randint(0, 5000, 10000)) def assert_equal_results(*results): primary_result = results[0] other_results = results[1:] for other_result in other_results: assert set(primary_result) == set(other_result) and len(primary_result) == len(other_result) if __name__ == '__main__': dups_count_time = TimerCounter() dups_count_dict_time = TimerCounter() dups_count_counter = TimerCounter() l = gen_array() for i in range(3): dups_count_time.start() result1 = dups_count(l) dups_count_time.stop() dups_count_dict_time.start() result2 = dups_count_dict(l) dups_count_dict_time.stop() dups_count_counter.start() result3 = dups_counter(l) dups_count_counter.stop() assert_equal_results(result1, result2, result3) print 'dups_count: %.3f' % dups_count_time.get_time_sum() print 'dups_count_dict: %.3f' % dups_count_dict_time.get_time_sum() print 'dups_count_counter: %.3f' % dups_count_counter.get_time_sum() 

Esta es la forma en que tuve que hacerlo porque me desafié a no usar otros métodos:

 def dupList(oldlist): if type(oldlist)==type((2,2)): oldlist=[x for x in oldlist] newList=[] newList=newList+oldlist oldlist=oldlist forbidden=[] checkPoint=0 for i in range(len(oldlist)): #print 'start i', i if i in forbidden: continue else: for j in range(len(oldlist)): #print 'start j', j if j in forbidden: continue else: #print 'after Else' if i!=j: #print 'i,j', i,j #print oldlist #print newList if oldlist[j]==oldlist[i]: #print 'oldlist[i],oldlist[j]', oldlist[i],oldlist[j] forbidden.append(j) #print 'forbidden', forbidden del newList[j-checkPoint] #print newList checkPoint=checkPoint+1 return newList 

por lo que su muestra funciona como:

 >>>a = [1,2,3,3,3,4,5,6,6,7] >>>dupList(a) [1, 2, 3, 4, 5, 6, 7] 

Al usar toolz :

 from toolz import frequencies, valfilter a = [1,2,2,3,4,5,4] >>> list(valfilter(lambda count: count > 1, frequencies(a)).keys()) [2,4] 

Estoy entrando mucho mucho más tarde en esta discusión. Aun así, me gustaría tratar este problema con una sola línea. Porque ese es el encanto de Python. Si solo queremos obtener los duplicados en una lista separada (o en cualquier colección), sugeriría hacer lo siguiente. Supongamos que tenemos una lista duplicada a la que podemos llamar “objective”.

  target=[1,2,3,4,4,4,3,5,6,8,4,3] 

Ahora, si queremos obtener los duplicados, podemos usar el forro de la siguiente manera:

  duplicates=dict(set((x,target.count(x)) for x in filter(lambda rec : target.count(rec)>1,target))) 

Este código colocará los registros duplicados como clave y contará como valor en el diccionario ‘duplicados’. El diccionario ‘duplicado’ se verá como a continuación:

  {3: 3, 4: 4} #it saying 3 is repeated 3 times and 4 is 4 times 

Si solo desea que todos los registros con duplicados solo en una lista, es un código mucho más corto:

  duplicates=filter(lambda rec : target.count(rec)>1,target) 

La salida será:

  [3, 4, 4, 4, 3, 4, 3] 

Esto funciona perfectamente en las versiones de python 2.7.x +

Método 1:

 list(set([val for idx, val in enumerate(input_list) if val in input_list[idx+1:]])) 

Explicación: [val para idx, val in enumerate (input_list) si val en input_list [idx + 1:]] es una lista de comprensión, que devuelve un elemento, si el mismo elemento está presente desde su posición actual, en la lista, el índice .

Ejemplo: input_list = [42,31,42,31,3,31,31,5,6,6,6,6,6,7,42]

comenzando con el primer elemento en la lista, 42, con el índice 0, comprueba si el elemento 42, está presente en input_list [1:] (es decir, desde el índice 1 hasta el final de la lista) Debido a que 42 está presente en input_list [1:] , volverá 42.

Luego pasa al siguiente elemento 31, con el índice 1, y comprueba si el elemento 31 está presente en la lista de entrada [2:] (es decir, desde el índice 2 hasta el final de la lista), porque 31 está presente en la lista de entrada [2:], volverá 31.

de manera similar, recorre todos los elementos de la lista y devolverá solo los elementos repetidos / duplicados en una lista.

Luego, debido a que tenemos duplicados, en una lista, debemos elegir uno de cada duplicado, es decir, eliminar duplicados entre duplicados, y para hacerlo, llamamos a un conjunto incorporado de python llamado (), y elimina los duplicados,

Luego nos quedamos con un conjunto, pero no una lista, y por lo tanto, para convertir de un conjunto a una lista, usamos, encasillamiento, lista (), y eso convierte el conjunto de elementos en una lista.

Método 2:

 def dupes(ilist): temp_list = [] # initially, empty temporary list dupe_list = [] # initially, empty duplicate list for each in ilist: if each in temp_list: # Found a Duplicate element if not each in dupe_list: # Avoid duplicate elements in dupe_list dupe_list.append(each) # Add duplicate element to dupe_list else: temp_list.append(each) # Add a new (non-duplicate) to temp_list return dupe_list 

Explicación: Aquí creamos dos listas vacías, para empezar. Luego, siga recorriendo todos los elementos de la lista para ver si existe en temp_list (inicialmente vacío). Si no está en la lista temp_list, entonces la agregamos a la lista temp, usando el método de adición.

Si ya existe en temp_list, significa que el elemento actual de la lista es un duplicado y, por lo tanto, debemos agregarlo a dupe_list mediante el método de adición.

 raw_list = [1,2,3,3,4,5,6,6,7,2,3,4,2,3,4,1,3,4,] clean_list = list(set(raw_list)) duplicated_items = [] for item in raw_list: try: clean_list.remove(item) except ValueError: duplicated_items.append(item) print(duplicated_items) # [3, 6, 2, 3, 4, 2, 3, 4, 1, 3, 4] 

Básicamente, se eliminan los duplicados convirtiéndolos en set ( clean_list ), luego se itera en raw_list , mientras se eliminan todos los item de la lista limpia para que aparezcan en raw_list . Si no se encuentra el elemento, la excepción ValueError se captura y el item se agrega a la lista duplicated_items .

If the index of duplicated items is needed, just enumerate the list and play around with the index. ( for index, item in enumerate(raw_list): ) which is faster and optimised for large lists (like thousands+ of elements)

Use the sort() function. Duplicates can be identified by looping over it and checking l1[i] == l1[i+1] .