¿Cómo puedo encontrar los duplicados en una lista de Python y crear otra lista de los duplicados? La lista solo contiene enteros.
python
list
duplicates
MFB
fuente
fuente
Respuestas:
Para eliminar duplicados use
set(a)
. Para imprimir duplicados, algo como:Tenga en cuenta que
Counter
no es particularmente eficiente ( tiempos ) y probablemente exagere aquí.set
funcionará mejor. Este código calcula una lista de elementos únicos en el orden de origen:o, más concisamente:
No recomiendo el último estilo, porque no es obvio lo que
not seen.add(x)
está haciendo (eladd()
método set siempre regresaNone
, de ahí la necesidad denot
).Para calcular la lista de elementos duplicados sin bibliotecas:
Si los elementos de la lista no son modificables, no puede usar conjuntos / dictos y debe recurrir a una solución de tiempo cuadrático (compare cada uno con cada uno). Por ejemplo:
fuente
O(n)
, porque solo itera la lista una vez y establece las búsquedasO(1)
.dup = []
else: dup.append(x)
print()
seen = set()
entoncesdupe = set(x for x in a if x in seen or seen.add(x))
fuente
l
conset(l)
sólo reduce el tiempo en el peor caso y por lo tanto no nada para abordar las cuestiones de eficiencia de mayor escala con esta respuesta. Probablemente no fue tan simple después de todo. En resumen, no hagas esto.No necesita el recuento, solo si el artículo se vio o no antes. Adaptado esa respuesta a este problema:
En caso de que la velocidad sea importante, aquí hay algunos tiempos:
Aquí están los resultados: (¡bien hecho @JohnLaRooy!)
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é del método que he sugerido parece no tener casi ningún efecto.
Aparentemente, este efecto está relacionado con la "duplicación" de los datos de entrada. He configurado
l = [random.randrange(1000000) for i in xrange(10000)]
y obtuve estos resultados:fuente
add
cada vez que fuera necesaria una inserción.pypy
si lo tienes a mano y buscas velocidad.Puedes usar
iteration_utilities.duplicates
:o si solo quieres uno de cada duplicado, esto se puede combinar con
iteration_utilities.unique_everseen
:También puede manejar elementos no compartibles (sin embargo, a costa del rendimiento):
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
O(n**2)
comportamiento.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:
Eliminando los
O(n**2)
enfoques, hice otro punto de referencia de hasta medio millón de elementos en una lista:Como puede ver, el
iteration_utilities.duplicates
enfoque es más rápido que cualquiera de los otros enfoques e incluso encadenamientounique_everseen(duplicates(...))
fue más rápido o igual de rápido que los otros enfoques.Una cosa interesante adicional a tener en cuenta aquí es que los enfoques de los pandas son muy lentos para listas pequeñas, pero pueden competir fácilmente por listas más largas.
Sin embargo, como muestran estos puntos de referencia, la mayoría de los enfoques tienen un rendimiento aproximadamente igual, por lo que no importa mucho cuál se use (excepto los 3 que tuvieron
O(n**2)
tiempo de ejecución).Benchmark 1
Benchmark 2
Descargo de responsabilidad
1 Se trata de una biblioteca de terceros que he escrito:
iteration_utilities
.fuente
Me encontré con esta pregunta mientras buscaba algo relacionado, y me pregunto por qué nadie ofreció una solución basada en un generador. Resolver este problema sería:
Estaba preocupado por la escalabilidad, por lo que probé varios enfoques, incluidos elementos ingenuos que funcionan bien en listas pequeñas, pero escalan horriblemente a medida que las listas se hacen más grandes (nota: habría sido mejor usar timeit, pero esto es ilustrativo).
Incluí @moooeeeep para la 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 aún más rápido nuevamente para listas en su mayoría ordenadas ... Ahora incluye el enfoque de pandas de @firelynx - lento, pero no horriblemente, y simple. Nota: el enfoque de clasificación / tee / zip es consistentemente más rápido en mi máquina para listas grandes en su mayoría ordenadas, moooeeeep es más rápido para listas barajadas, pero su millaje puede variar.
Ventajas
Supuestos
La solución más rápida, 1 millón de entradas:
Enfoques probados
Los resultados para la prueba de 'todos los duplicados' fueron consistentes, encontrando "primero" duplicado y luego "todos" duplicados en esta matriz:
Cuando las listas se barajan primero, el precio del tipo se hace evidente: la eficiencia cae notablemente y el enfoque @moooeeeep domina, con enfoques set & dict que son similares pero de menor rendimiento:
fuente
random.shuffle(c)
dar cuenta de eso. Además, tampoco puedo replicar sus resultados cuando ejecuto el script inalterado (un orden totalmente diferente), por lo que tal vez también dependa de la CPU.Usando pandas:
fuente
collections.Counter es nuevo en python 2.7:
En una versión anterior, puede usar un dict convencional en su lugar:
fuente
Aquí hay una solución ordenada y concisa:
fuente
Sin convertir a la lista y probablemente la forma más simple sería algo como a continuación. Esto puede ser útil durante una entrevista cuando piden no usar sets
======= más para obtener 2 listas separadas de valores únicos y valores duplicados
fuente
Haría esto con los pandas, porque los uso mucho
Da
Probablemente no sea muy eficiente, pero seguro es menos código que muchas de las otras respuestas, así que pensé que contribuiría
fuente
pda = pd.Series(a)
print list(pda[pda.duplicated()])
El tercer ejemplo de la respuesta aceptada da una respuesta errónea y no intenta dar duplicados. Aquí está la versión correcta:
fuente
¿Qué tal si simplemente recorre cada elemento de la lista verificando el número de ocurrencias y luego agregándolos a un conjunto que luego imprimirá los duplicados? Espero que esto ayude a alguien por ahí.
fuente
Podemos usar
itertools.groupby
para encontrar todos los artículos que tienen dups:El resultado será:
fuente
dupes = [x for x, y in groupby(sorted(myList)) if len(list(y)) > 1]
Creo que la forma más efectiva de encontrar duplicados en una lista es:
Utiliza
Counter
todos los elementos y todos los elementos únicos. Restar el primero con el segundo dejará fuera solo los duplicados.fuente
Un poco tarde, pero tal vez útil para algunos. Para una lista grande, encontré que esto funcionó para mí.
Muestra solo y todos los duplicados y conserva el orden.
fuente
La forma muy simple y rápida de encontrar personas engañadas con una iteración en Python es:
La salida será la siguiente:
Esto y más en mi blog http://www.howtoprogramwithpython.com
fuente
Estoy entrando mucho más tarde en esta discusión. Sin embargo, me gustaría tratar este problema con un revestimiento. Porque ese es el encanto de Python. si solo queremos obtener los duplicados en una lista separada (o cualquier colección), sugeriría hacer lo siguiente: digamos que tenemos una lista duplicada que podemos llamar como 'objetivo'
Ahora, si queremos obtener los duplicados, podemos usar el único revestimiento de la siguiente manera:
Este código colocará los registros duplicados como clave y contará como valor en el diccionario 'duplicados'. El diccionario 'duplicado' tendrá el siguiente aspecto:
Si solo desea todos los registros con duplicados solo en una lista, nuevamente es un código mucho más corto:
La salida será:
Esto funciona perfectamente en las versiones de python 2.7.x +
fuente
Python 3.8 one-liner si no le importa escribir su propio algoritmo o usar bibliotecas:
Imprime el artículo y cuenta:
groupby
toma una función de agrupación para que pueda definir sus agrupaciones de diferentes maneras y devolverTuple
campos adicionales según sea necesario.groupby
es vago, por lo que no debería ser demasiado lento.fuente
Algunas otras pruebas. Por supuesto que hacer ...
... es muy costoso. Es aproximadamente 500 veces más rápido (la matriz más larga da mejores resultados) para usar el siguiente método final:
Solo 2 bucles, sin
l.count()
operaciones muy costosas .Aquí hay un código para comparar los métodos, por ejemplo. El código está abajo, aquí está la salida:
El código de prueba:
fuente
Método 1:
Explicación: [val para idx, val en enumerate (input_list) si val en input_list [idx + 1:]] es una comprensión de la lista, 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, verifica si el elemento 42 está presente en input_list [1:] (es decir, desde el índice 1 hasta el final de la lista) Porque 42 está presente en input_list [1:] , devolverá 42.
Luego va al siguiente elemento 31, con el índice 1, y verifica si el elemento 31 está presente en input_list [2:] (es decir, desde el índice 2 hasta el final de la lista), porque 31 está presente en input_list [2:], devolverá 31.
de manera similar, revisa todos los elementos de la lista y solo devolverá los elementos repetidos / duplicados en una lista.
Luego, debido a que tenemos duplicados, en una lista, necesitamos elegir uno de cada duplicado, es decir, eliminar duplicados entre duplicados, y para hacerlo, llamamos a un conjunto de nombres incorporado de Python (), y elimina los duplicados,
Luego nos queda un conjunto, pero no una lista, y por lo tanto, para convertir de un conjunto a una lista, usamos typecasting, list (), y eso convierte el conjunto de elementos en una lista.
Método 2:
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á allí en temp_list, entonces lo agregamos a temp_list, usando el método append .
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 usando el método append .
fuente
Básicamente, elimina los duplicados convirtiéndolos en set (
clean_list
), luego iteraraw_list
, mientras elimina cada unoitem
en la lista limpia para que ocurraraw_list
. Siitem
no se encuentra,ValueError
se captura la excepción generada yitem
se agrega a laduplicated_items
lista.Si se necesita el índice de elementos duplicados, solo
enumerate
la lista y juegue con el índice. (for index, item in enumerate(raw_list):
) que es más rápido y optimizado para listas grandes (como miles + de elementos)fuente
uso del
list.count()
método en la lista para descubrir los elementos duplicados de una lista dadafuente
one-liner, por diversión, y donde se requiere una sola declaración.
fuente
fuente
Solución de una línea:
fuente
Aquí hay muchas respuestas, pero creo que este es un enfoque relativamente fácil de leer y de entender:
Notas:
fuente
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 ha sido entregado.
Para listas con todos los elementos que son tipos hashable:
Para listas que pueden contener listas:
fuente
fuente
Al usar toolz :
fuente
esta es la forma en que tuve que hacerlo porque me desafié a mí mismo a no usar otros métodos:
entonces su muestra funciona como:
fuente
duplist = list(set(a))
.