In questa risposta, ci saranno due sezioni: due soluzioni uniche e un grafico della velocità per soluzioni specifiche.
Rimozione di elementi duplicati
La maggior parte di queste risposte rimuove solo gli oggetti duplicati che sono lavabili , ma questa domanda non implica che non abbia solo bisogno di oggetti lavabili , il che significa che offrirò alcune soluzioni che non richiedono oggetti lavabili .
collezioni.Counter è un potente strumento nella libreria standard che potrebbe essere perfetto per questo. C'è solo un'altra soluzione che ha persino Counter. Tuttavia, tale soluzione si limita anche alle chiavi cancellabili .
Per consentire le chiavi non cancellabili in Counter, ho creato una classe Container, che tenterà di ottenere la funzione hash predefinita dell'oggetto, ma se fallisce, proverà la sua funzione di identità. Definisce anche un metodo eq e un metodo hash . Questo dovrebbe essere sufficiente per consentire articoli non lavabili nella nostra soluzione. Gli oggetti non lavabili verranno trattati come se fossero cancellabili. Tuttavia, questa funzione hash utilizza l'identità per oggetti non lavabili, il che significa che due oggetti uguali che sono entrambi non lavabili non funzioneranno. Ti suggerisco di ignorare questo e di cambiarlo per usare l'hash di un tipo mutabile equivalente (come usare hash(tuple(my_list))
se my_list
è un elenco).
Ho anche fatto due soluzioni. Un'altra soluzione che mantiene l'ordine degli articoli, usando una sottoclasse di OrderedDict e Counter che si chiama 'OrderedCounter'. Ora, ecco le funzioni:
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 è l'ordinamento non ordinato, oremd è l'ordinamento ordinato. Puoi dire chiaramente quale è più veloce, ma lo spiegherò comunque. L'ordinamento non ordinato è leggermente più veloce. Mantiene meno dati, poiché non ha bisogno di ordine.
Ora, volevo anche mostrare i confronti di velocità di ciascuna risposta. Quindi, lo farò ora.
Quale funzione è la più veloce?
Per rimuovere i duplicati, ho raccolto 10 funzioni da alcune risposte. Ho calcolato la velocità di ciascuna funzione e l'ho inserita in un grafico usando matplotlib.pyplot .
L'ho diviso in tre turni di rappresentazione grafica. Un hashable è qualsiasi oggetto che può essere sottoposto a hash, un non lavabile è qualsiasi oggetto che non può essere hash. Una sequenza ordinata è una sequenza che conserva l'ordine, una sequenza non ordinata non conserva l'ordine. Ora, ecco alcuni altri termini:
Hashable non ordinato era per qualsiasi metodo che rimuoveva i duplicati, che non doveva necessariamente mantenere l'ordine. Non ha dovuto funzionare per inhahable, ma potrebbe.
Hashable ordinato è stato per qualsiasi metodo che ha mantenuto l'ordine degli elementi nell'elenco, ma non ha dovuto funzionare per gli inhahable, ma poteva.
Ordered Unhashable è stato qualsiasi metodo che ha mantenuto l'ordine degli articoli nell'elenco e ha funzionato in modo insostituibile.
Sull'asse y è la quantità di secondi impiegata.
Sull'asse x è presente il numero a cui è stata applicata la funzione.
Abbiamo generato sequenze di hashble non ordinati e ordinato hashable con la seguente comprensione: [list(range(x)) + list(range(x)) for x in range(0, 1000, 10)]
Per gli insostituibili ordinati: [[list(range(y)) + list(range(y)) for y in range(x)] for x in range(0, 1000, 10)]
Nota che c'è un "passo" nell'intervallo perché senza di esso, questo avrebbe richiesto 10 volte più tempo. Anche perché secondo la mia opinione personale, ho pensato che avrebbe potuto sembrare un po 'più facile da leggere.
Nota anche che i tasti della legenda sono quelli che ho cercato di indovinare come le parti più vitali della funzione. Per quanto riguarda quale funzione fa il peggio o il meglio? Il grafico parla da solo.
Con quello risolto, ecco i grafici.
Hashables non ordinati
(Ingrandito)
Hashables ordinati
(Ingrandito)
Non ordinabili ordinati
(Ingrandito)