外部モジュールからそのような機能の別の(非常にパフォーマンスの高い)実装を追加するだけです1 : iteration_utilities.unique_everseen
:
>>> from iteration_utilities import unique_everseen
>>> lst = [1,1,1,2,3,2,2,2,1,3,4]
>>> list(unique_everseen(lst))
[1, 2, 3, 4]
タイミング
私はいくつかのタイミング(Python 3.6)を実行しましたが、これらは、テストした他のすべての代替手段よりも高速であることを示してOrderedDict.fromkeys
いf7
ますmore_itertools.unique_everseen
。
%matplotlib notebook
from iteration_utilities import unique_everseen
from collections import OrderedDict
from more_itertools import unique_everseen as mi_unique_everseen
def f7(seq):
seen = set()
seen_add = seen.add
return [x for x in seq if not (x in seen or seen_add(x))]
def iteration_utilities_unique_everseen(seq):
return list(unique_everseen(seq))
def more_itertools_unique_everseen(seq):
return list(mi_unique_everseen(seq))
def odict(seq):
return list(OrderedDict.fromkeys(seq))
from simple_benchmark import benchmark
b = benchmark([f7, iteration_utilities_unique_everseen, more_itertools_unique_everseen, odict],
{2**i: list(range(2**i)) for i in range(1, 20)},
'list size (no duplicates)')
b.plot()
そして、それが違いを生むかどうかを確認するためだけに、より多くの重複を使用してテストも行ったことを確認するために:
import random
b = benchmark([f7, iteration_utilities_unique_everseen, more_itertools_unique_everseen, odict],
{2**i: [random.randint(0, 2**(i-1)) for _ in range(2**i)] for i in range(1, 20)},
'list size (lots of duplicates)')
b.plot()
そして、値を 1 つだけ含むもの:
b = benchmark([f7, iteration_utilities_unique_everseen, more_itertools_unique_everseen, odict],
{2**i: [1]*(2**i) for i in range(1, 20)},
'list size (only duplicates)')
b.plot()
これらのすべてのケースで、iteration_utilities.unique_everseen
関数は (私のコンピューター上で) 最速です。
このiteration_utilities.unique_everseen
関数は、入力内のハッシュ不可能な値も処理できます (ただし、値がハッシュ可能である場合O(n*n)
は、パフォーマンスではなくパフォーマンスを使用O(n)
します)。
>>> lst = [{1}, {1}, {2}, {1}, {3}]
>>> list(unique_everseen(lst))
[{1}, {2}, {3}]
1免責事項: 私はそのパッケージの作成者です。