Bu cevapta iki bölüm olacak: İki benzersiz çözüm ve belirli çözümler için bir hız grafiği.
Yinelenen Öğeleri Kaldırma
Bu cevapların çoğu sadece yıkanabilir yinelenen öğeleri kaldırır , ancak bu soru sadece yıkanabilir öğelere ihtiyaç duymadığı anlamına gelmez , yani yıkanabilir öğeler gerektirmeyen bazı çözümler sunacağım .
Counter , standart kütüphanede bunun için mükemmel olabilecek güçlü bir araçtır. Counter bile olan başka bir çözüm daha var. Ancak bu çözüm, yıkanabilir tuşlarla da sınırlıdır .
Sayaç'ta paylaşılamayan anahtarlara izin vermek için, nesnenin varsayılan karma işlevini almaya çalışacak bir Container sınıfı yaptım, ancak başarısız olursa, kimlik işlevini deneyecek. Aynı zamanda bir eq ve hash yöntemini tanımlar . Bu, çözümümüzde paylaşılamaz öğelere izin vermek için yeterli olmalıdır . Shahable nesnelere yıkanabilirmiş gibi davranılır. Ancak, bu karma işlevi, paylaşılamayan nesneler için kimlik kullanır, yani her ikisi de paylaşılamayan iki eşit nesne çalışmaz. Bunu geçersiz kılma ve kullanma gibi (eşdeğer bir değişken türü karmasını kullanmak değiştirmeyi önermek hash(tuple(my_list))
eğermy_list
bir list ).
İki çözüm de yaptım. 'OrderedCounter' adında bir OrdierDict ve Counter alt sınıfı kullanarak öğelerin sırasını koruyan başka bir çözüm. Şimdi, fonksiyonlar şunlardır:
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 sıralı değil, oremd sıralı. Hangisinin daha hızlı olduğunu açıkça anlayabilirsiniz, ama yine de açıklayacağım. Sıralanmamış sıralama biraz daha hızlıdır. Düzen gerektirmediği için daha az veri tutar.
Şimdi, her cevabın hız karşılaştırmalarını da göstermek istedim. Şimdi bunu yapacağım.
En Hızlı Hangi İşlev?
Kopyaları kaldırmak için, birkaç cevaptan 10 fonksiyon topladım. Her işlevin hızını hesapladım ve matplotlib.pyplot kullanarak bir grafiğe koydum .
Bunu üç grafik turuna ayırdım. Yıkanabilir hashedilebilen herhangi bir nesnedir, paylaşılamaz hash edilemeyen herhangi bir nesnedir. Sıralı bir sıra, düzeni koruyan bir sıradır, sırasız bir sıra sıralamayı korumaz. Şimdi, birkaç terim daha:
Sırasız Yıkanabilir , siparişleri korumak zorunda olmayan kopyaları kaldıran herhangi bir yöntem . Tıraşsızlar için çalışmak zorunda değildi, ama olabilirdi.
Sipariş Edilebilir Yıkanabilir , listedeki öğelerin sırasını koruyan herhangi bir yöntem içindi, ancak shahables için çalışmak zorunda değildi, ancak olabilirdi.
Shahable sipariş edildi , listedeki öğelerin sırasını koruyan ve için çalışan herhangi bir yöntemdi.
Y ekseninde geçen saniye miktarı.
X ekseninde, işlevin uygulandığı sayıdır.
Sırasız hashable'lar için diziler oluşturduk ve aşağıdaki kavrayışla hashables sipariş ettik: [list(range(x)) + list(range(x)) for x in range(0, 1000, 10)]
Sipariş edilen unhashables için: [[list(range(y)) + list(range(y)) for y in range(x)] for x in range(0, 1000, 10)]
Aralıkta bir 'adım' olduğuna dikkat edin, çünkü onsuz bu 10 kat daha uzun sürecektir. Ayrıca kişisel görüşüme göre, okunması biraz daha kolay görünebileceğini düşündüm.
Ayrıca, efsane üzerindeki tuşların, işlevin en önemli parçaları olarak tahmin etmeye çalıştığım şeyler olduğuna dikkat edin. En kötü ya da en iyi hangi işlev için? Grafik kendisi için konuşur.
Bu kararla birlikte, grafikler burada.
Sırasız Hashables
(Yakınlaştırılmış)
Sipariş Edilen Hashables
(Yakınlaştırılmış)
Sipariş Edilemeyen Shahables
(Yakınlaştırılmış)