python - repetidos - Eliminar duplicados en listas
python eliminar duplicados de una lista (30)
Más o menos necesito escribir un programa para verificar si una lista tiene duplicados y si los elimina y devuelve una nueva lista con los elementos que no se duplicaron / eliminaron. Esto es lo que tengo, pero para ser honesto, no sé qué hacer.
def remove_duplicates():
t = [''a'', ''b'', ''c'', ''d'']
t2 = [''a'', ''c'', ''d'']
for t in t2:
t.append(t.remove())
return t
A este le importa el pedido sin demasiados problemas (OrderdDict y otros). Probablemente no sea la forma más pitónica, ni la más corta, pero tiene el truco:
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
Aquí está la solución pythonic más rápida comparada con otras personas que figuran en las respuestas.
El uso de los detalles de implementación de la evaluación de cortocircuito permite usar la comprensión de lista, que es lo suficientemente rápida. visited.add(item)
siempre devuelve None
como resultado, que se evalúa como False
, por lo que el lado derecho or
siempre será el resultado de dicha expresión.
Tiempo de ti mismo
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
Aquí hay un ejemplo, regresando a la lista sin repeticiones manteniendo el orden. No necesita ninguna importación externa.
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
Creo que convertir para establecer es la forma más fácil de eliminar duplicados:
list1 = [1,2,1]
list1 = list(set(list1))
print list1
El enfoque común para obtener una colección única de artículos es utilizar un set
. Los conjuntos son colecciones desordenadas de objetos distintos . Para crear un conjunto de cualquier iterable, simplemente puede pasarlo a la función integrada set()
. Si luego vuelve a necesitar una lista real, también puede pasar el conjunto a la función list()
.
El siguiente ejemplo debería abarcar lo que esté tratando de hacer:
>>> 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]
Como puede ver en el resultado del ejemplo, el pedido original no se mantiene. Como se mencionó anteriormente, los conjuntos en sí mismos son colecciones desordenadas, por lo que el orden se pierde. Al convertir un conjunto de nuevo a una lista, se crea un orden arbitrario.
Si el orden es importante para usted, entonces tendrá que usar un mecanismo diferente. Una solución muy común para esto es confiar en OrderedDict
para mantener el orden de las claves durante la inserción:
>>> from collections import OrderedDict
>>> list(OrderedDict.fromkeys(t))
[1, 2, 3, 5, 6, 7, 8]
Tenga en cuenta que esto tiene la sobrecarga de crear primero un diccionario y luego crear una lista a partir de él. Entonces, si realmente no necesitas conservar el orden, es mejor que uses un juego. Echa un vistazo a esta pregunta para obtener más detalles y formas alternativas de conservar el orden al eliminar duplicados.
Finalmente, tenga en cuenta que tanto el set
como la solución OrderedDict
requieren que sus elementos sean hashable . Esto generalmente significa que tienen que ser inmutables. Si tiene que lidiar con elementos que no son hashable (por ejemplo, enumerar objetos), entonces tendrá que usar un enfoque lento en el que básicamente tendrá que comparar cada elemento con cada otro elemento en un bucle anidado.
El mejor método para eliminar duplicados de una lista es usar la función set () , disponible en Python, que convierte de nuevo ese conjunto en lista
In [2]: some_list = [''a'',''a'',''v'',''v'',''v'',''c'',''c'',''d'']
In [3]: list(set(some_list))
Out[3]: [''a'', ''c'', ''d'', ''v'']
El siguiente código es simple para eliminar duplicados en la lista
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])
devuelve [1,2,3,4]
Es de una sola línea: list(set(source_list))
hará el truco.
Un set
es algo que no puede tener duplicados.
Actualización: un enfoque de preservación de orden es de dos líneas:
from collections import OrderedDict
OrderedDict((x, True) for x in source_list).keys()
Aquí utilizamos el hecho de que OrderedDict
recuerda el orden de inserción de las claves, y no lo cambia cuando se actualiza un valor en una clave en particular. Insertamos True
como valores, pero podríamos insertar cualquier cosa, los valores simplemente no se usan. ( set
funciona como un dict
con valores ignorados).
Hay muchas otras respuestas que sugieren diferentes maneras de hacer esto, pero todas son operaciones por lotes, y algunas de ellas desechan el pedido original. Eso podría estar bien dependiendo de lo que necesite, pero si desea iterar sobre los valores en el orden de la primera instancia de cada valor, y desea eliminar los duplicados sobre la marcha en lugar de todos a la vez, puede usar este generador:
def uniqify(iterable):
seen = set()
for item in iterable:
if item not in seen:
seen.add(item)
yield item
Esto devuelve un generador / iterador, por lo que puede usarlo en cualquier lugar que pueda usar un iterador.
for unique_item in uniqify([1, 2, 3, 4, 3, 2, 4, 5, 6, 7, 6, 8, 8]):
print(unique_item, end='' '')
print()
Salida:
1 2 3 4 5 6 7 8
Si quieres una list
, puedes hacer esto:
unique_list = list(uniqify([1, 2, 3, 4, 3, 2, 4, 5, 6, 7, 6, 8, 8]))
print(unique_list)
Salida:
[1, 2, 3, 4, 5, 6, 7, 8]
Hoy en día podrías usar la clase Counter:
>>> 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])
Manera muy 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]
Marque esto si desea eliminar los duplicados (edición in situ en lugar de devolver una nueva lista) sin usar el conjunto incorporado, dict.keys, uniqify, counter
>>> 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]
Otra forma de hacer:
>>> seq = [1,2,3,''a'', ''a'', 1,2]
>> dict.fromkeys(seq).keys()
[''a'', 1, 2, 3]
Para eliminar los duplicados, conviértalo en un SET y luego en una LISTA e imprímalo / úselo. Un conjunto está garantizado para tener elementos únicos. Por ejemplo :
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 salida será la siguiente (verificada 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!!
Para hacer una nueva lista reteniendo el orden de los primeros elementos de duplicados en L
newlist=[ii for n,ii in enumerate(L) if ii not in L[:n]]
por ejemplo, if L=[1, 2, 2, 3, 4, 2, 4, 3, 5]
entonces newlist
será [1,2,3,4,5]
Esto comprueba que cada elemento nuevo no haya aparecido previamente en la lista antes de agregarlo. Tampoco necesita importaciones.
Puedes hacer esto simplemente usando sets.
Paso 1: Consigue diferentes elementos de listas
Paso 2 Consigue elementos comunes de listas
Step3 Combínalos
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''}
Puedes usar set
para eliminar duplicados:
mylist = list(set(mylist))
Pero tenga en cuenta que los resultados serán desordenados. Si eso es un problema:
mylist.sort()
Reducir variante con preservar de pedido:
Supongamos que tenemos lista:
l = [5, 6, 6, 1, 1, 2, 2, 3, 4]
Reducir variante (ineficiente):
>>> reduce(lambda r, v: v in r and r or r + [v], l, [])
[5, 6, 1, 2, 3, 4]
5 veces más rápido pero más sofisticado
>>> 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]
Explicación:
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]
Si no te importa el pedido, haz esto:
def remove_duplicates(l):
return list(set(l))
Se garantiza que un set
no tiene duplicados.
Simple y fácil:
myList = [1, 2, 3, 1, 2, 5, 6, 7, 8]
cleanlist = []
[cleanlist.append(x) for x in myList if x not in cleanlist]
Salida:
>>> cleanlist
[1, 2, 3, 5, 6, 7, 8]
Sin usar 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)
También hay soluciones usando Pandas y Numpy. Ambos devuelven una matriz numpy, así que tienes que usar la función .tolist()
si quieres una lista.
t=[''a'',''a'',''b'',''b'',''b'',''c'',''c'',''c'']
t2= [''c'',''c'',''b'',''b'',''b'',''a'',''a'',''a'']
Solución de pandas
Usando la función de Pandas unique()
:
import pandas as pd
pd.unique(t).tolist()
>>>[''a'',''b'',''c'']
pd.unique(t2).tolist()
>>>[''c'',''b'',''a'']
Solución de numpy
Usando la función numpy unique()
.
import numpy as np
np.unique(t).tolist()
>>>[''a'',''b'',''c'']
np.unique(t2).tolist()
>>>[''a'',''b'',''c'']
Tenga en cuenta que numpy.unique () también ordena los valores . Así que la lista t2
se devuelve ordenada. Si desea que se conserve el orden, utilice como en esta respuesta :
_, idx = np.unique(t2, return_index=True)
t2[np.sort(idx)].tolist()
>>>[''c'',''b'',''a'']
Sin embargo, la solución no es tan elegante en comparación con las otras, en comparación con pandas.unique (), numpy.unique () también le permite verificar si las matrices anidadas son únicas en un eje seleccionado.
También podrías hacer esto:
>>> 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 razón por la que funciona anteriormente es que el método de index
solo devuelve el primer índice de un elemento. Los elementos duplicados tienen índices más altos. Consulte here :
list.index (x [, start [, end]])
Devuelve el índice de base cero en la lista del primer elemento cuyo valor es x. Genera un ValueError si no hay tal elemento.
Tenía un dictado en mi lista, por lo que no podía usar el enfoque anterior. Me salió el error
TypeError: unhashable type:
Así que si te importa el orden y / o algunos artículos son inestables . Entonces podrías encontrar esto útil:
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
Algunos pueden considerar la comprensión de la lista con un efecto secundario para no ser una buena solución. Aquí hay una alternativa:
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
Todos los enfoques para preservar el orden que he visto hasta ahora utilizan una comparación ingenua (con O (n ^ 2) complejidad de tiempo en el mejor de los casos) o combinaciones de list
/ OrderedDicts
pesos OrderedDicts
que se limitan a entradas de hashable. Aquí hay una solución O (nlogn) independiente de hash:
Update agregó el argumento key
, la documentación y la compatibilidad con 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]]))]
Trate de usar conjuntos:
import sets
t = sets.Set([''a'', ''b'', ''c'', ''d''])
t1 = sets.Set([''a'', ''b'', ''c''])
print t | t1
print t - t1
Un colega me envió la respuesta aceptada como parte de su código para una revisión de código hoy. Aunque ciertamente admiro la elegancia de la respuesta en cuestión, no estoy contento con el rendimiento. He probado esta solución (uso set para reducir el tiempo de búsqueda)
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
Para comparar la eficiencia, utilicé una muestra aleatoria de 100 enteros: 62 eran únicos
from random import randint
x = [randint(0,100) for _ in xrange(100)]
In [131]: len(set(x))
Out[131]: 62
Aquí están los resultados de las mediciones.
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
Bueno, ¿qué pasa si el conjunto se elimina de la solución?
def ordered_set(inlist):
out_list = []
for val in inlist:
if not val in out_list:
out_list.append(val)
return out_list
El resultado no es tan malo como con OrderedDict , pero aún más de 3 veces de la solución original
In [136]: %timeit ordered_set(x)
10000 loops, best of 3: 52.6 us per loop
Utilizando set :
a = [0,1,2,3,4,3,3,4]
a = list(set(a))
print a
Utilizando único :
import numpy as np
a = [0,1,2,3,4,3,3,4]
a = np.unique(a).tolist()
print a
En Python 2.7 , la nueva forma de eliminar duplicados de un iterable mientras se mantiene en el orden original es:
>>> from collections import OrderedDict
>>> list(OrderedDict.fromkeys(''abracadabra''))
[''a'', ''b'', ''r'', ''c'', ''d'']
En Python 3.5 , OrderedDict tiene una implementación en C. Mis tiempos muestran que este es ahora el más rápido y el más corto de los diversos enfoques para Python 3.5.
En Python 3.6 , el dict regular se volvió ordenado y compacto. (Esta característica es válida para CPython y PyPy, pero puede no estar presente en otras implementaciones). Eso nos da una nueva forma más rápida de dedupir y retener el orden:
>>> list(dict.fromkeys(''abracadabra''))
[''a'', ''b'', ''r'', ''c'', ''d'']
En Python 3.7 , el dictado regular está garantizado para ambos ordenados en todas las implementaciones. Entonces, la solución más rápida y rápida es:
>>> list(dict.fromkeys(''abracadabra''))
[''a'', ''b'', ''r'', ''c'', ''d'']
>>> 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]