En esta respuesta, habrá dos secciones: dos soluciones únicas y un gráfico de velocidad para soluciones específicas.
Eliminar elementos duplicados
La mayoría de estas respuestas solo eliminan los elementos duplicados que son hashables , pero esta pregunta no implica que no solo necesite elementos hashable , lo que significa que ofreceré algunas soluciones que no requieren elementos hashaable .
colecciones.Counter es una herramienta poderosa en la biblioteca estándar que podría ser perfecta para esto. Solo hay otra solución que incluso tiene Counter. Sin embargo, esa solución también se limita a las claves hashaable .
Para permitir claves no compartibles en Counter, hice una clase Container, que intentará obtener la función hash predeterminada del objeto, pero si falla, probará su función de identidad. También define una ecuación y un método hash . Esto debería ser suficiente para permitir elementos no compartibles en nuestra solución. Los objetos no compartibles serán tratados como si fueran hashables. Sin embargo, esta función hash usa identidad para objetos no compartibles, lo que significa que dos objetos iguales que son ambos no compartibles no funcionarán. Le sugiero que anule esto y lo cambie para usar el hash de un tipo mutable equivalente (como usar hash(tuple(my_list))
if my_list
es una lista).
También hice dos soluciones. Otra solución que mantiene el orden de los elementos, usando una subclase de OrderedDict y Counter que se llama 'OrderedCounter'. Ahora, aquí están las funciones:
from collections import OrderedDict, Counter
class Container:
def __init__(self, obj):
self.obj = obj
def __eq__(self, obj):
return self.obj == obj
def __hash__(self):
try:
return hash(self.obj)
except:
return id(self.obj)
class OrderedCounter(Counter, OrderedDict):
'Counter that remembers the order elements are first encountered'
def __repr__(self):
return '%s(%r)' % (self.__class__.__name__, OrderedDict(self))
def __reduce__(self):
return self.__class__, (OrderedDict(self),)
def remd(sequence):
cnt = Counter()
for x in sequence:
cnt[Container(x)] += 1
return [item.obj for item in cnt]
def oremd(sequence):
cnt = OrderedCounter()
for x in sequence:
cnt[Container(x)] += 1
return [item.obj for item in cnt]
remd es una ordenación no ordenada, oremd es una ordenación ordenada. Puedes decir claramente cuál es más rápido, pero te lo explicaré de todos modos. La ordenación no ordenada es un poco más rápida. Mantiene menos datos, ya que no necesita orden.
Ahora, también quería mostrar las comparaciones de velocidad de cada respuesta. Entonces, lo haré ahora.
¿Qué función es la más rápida?
Para eliminar duplicados, reuní 10 funciones de algunas respuestas. Calculé la velocidad de cada función y la puse en un gráfico usando matplotlib.pyplot .
Dividí esto en tres rondas de gráficos. Un hashable es cualquier objeto que puede ser hash, un no hashable es cualquier objeto que no puede ser hash. Una secuencia ordenada es una secuencia que conserva el orden, una secuencia desordenada no conserva el orden. Ahora, aquí hay algunos términos más:
Hashable desordenado era para cualquier método que eliminara duplicados, que no necesariamente tenía que mantener el orden. No tenía que funcionar para los incontrolables, pero podía.
Hashable ordenado era para cualquier método que mantuviera el orden de los elementos en la lista, pero no tenía que funcionar para los no compartibles, pero podía.
Ordenado no compartible era cualquier método que mantenía el orden de los elementos de la lista y funcionaba para los no compartibles.
En el eje y es la cantidad de segundos que tardó.
En el eje x es el número al que se aplicó la función.
Generamos secuencias para hashables no ordenados y hashables ordenados con la siguiente comprensión: [list(range(x)) + list(range(x)) for x in range(0, 1000, 10)]
Para los no compartidos ordenados: [[list(range(y)) + list(range(y)) for y in range(x)] for x in range(0, 1000, 10)]
Tenga en cuenta que hay un 'paso' en el rango porque sin él, esto hubiera tardado 10 veces más. También porque, en mi opinión personal, pensé que podría haber sido un poco más fácil de leer.
También tenga en cuenta que las teclas de la leyenda son lo que traté de adivinar como las partes más vitales de la función. ¿En cuanto a qué función hace lo peor o lo mejor? El gráfico habla por sí mismo.
Con eso resuelto, aquí están los gráficos.
Hashables desordenados
(Aumentado)
Hashables ordenados
(Aumentado)
Ordenadas inquebrantables
(Aumentado)