Просто для добавления другой (очень производительной) реализации такой функциональности из внешнего модуля 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()
И один, содержащий только одно значение:
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 Отказ от ответственности: я являюсь автором этого пакета.