Python'da bir liste listem var:
k = [[1, 2], [4], [5, 6, 2], [1, 2], [3], [4]]
Ve ondan yinelenen öğeleri kaldırmak istiyorum. Normal bir liste olsaydı kullanabileceğim listelerin değil set. Ancak ne yazık ki bu liste hashable değildir ve bir dizi liste oluşturamaz. Sadece tuplelar. Böylece tüm listeleri demetlere çevirebilirim, sonra set ve listelere geri dönebilirim. Ama bu hızlı değil.
Bu en verimli şekilde nasıl yapılabilir?
Yukarıdaki listenin sonucu şöyle olmalıdır:
k = [[5, 6, 2], [1, 2], [3], [4]]
Düzeni korumak umurumda değil.
Not: Bu soru benzer, ancak tam olarak ihtiyacım olan şey değil. SO arandı ancak tam olarak yinelenen öğe bulunamadı
Kıyaslama:
import itertools, time
class Timer(object):
def __init__(self, name=None):
self.name = name
def __enter__(self):
self.tstart = time.time()
def __exit__(self, type, value, traceback):
if self.name:
print '[%s]' % self.name,
print 'Elapsed: %s' % (time.time() - self.tstart)
k = [[1, 2], [4], [5, 6, 2], [1, 2], [3], [5, 2], [6], [8], [9]] * 5
N = 100000
print len(k)
with Timer('set'):
for i in xrange(N):
kt = [tuple(i) for i in k]
skt = set(kt)
kk = [list(i) for i in skt]
with Timer('sort'):
for i in xrange(N):
ks = sorted(k)
dedup = [ks[i] for i in xrange(len(ks)) if i == 0 or ks[i] != ks[i-1]]
with Timer('groupby'):
for i in xrange(N):
k = sorted(k)
dedup = list(k for k, _ in itertools.groupby(k))
with Timer('loop in'):
for i in xrange(N):
new_k = []
for elem in k:
if elem not in new_k:
new_k.append(elem)
Kısa listeler için en hızlısı "döngü içinde" (ikinci dereceden yöntem). Uzun listeler için, groupby yöntemi dışında herkesten daha hızlıdır. Bu mantıklı mı?
Kısa liste için (koddaki), 100000 yineleme:
[set] Elapsed: 1.3900001049
[sort] Elapsed: 0.891000032425
[groupby] Elapsed: 0.780999898911
[loop in] Elapsed: 0.578000068665
Daha uzun liste için (koddaki liste 5 kez çoğaltılmıştır):
[set] Elapsed: 3.68700003624
[sort] Elapsed: 3.43799996376
[groupby] Elapsed: 1.03099989891
[loop in] Elapsed: 1.85900020599