В этом ответе будут два раздела: два уникальных решения и график скорости для конкретных решений.
Удаление дубликатов
В большинстве из этих ответов удаляются только дублирующиеся элементы, которые можно хэшировать , но этот вопрос не означает, что ему нужны не только хэшируемые элементы, а это означает, что я предложу некоторые решения, которые не требуют хэшируемых элементов.
collection.Counter - это мощный инструмент в стандартной библиотеке, который идеально подходит для этого. Есть только одно решение, в котором даже есть Counter. Однако это решение также ограничено хэшируемыми ключами.
Чтобы разрешить неиспользуемые ключи в Counter, я создал класс Container, который попытается получить хеш-функцию объекта по умолчанию, но в случае сбоя он попытается использовать функцию идентификации. Он также определяет eq и метод хэширования . Этого должно быть достаточно, чтобы в нашем решении не было нежелательных предметов. Нежелательные объекты будут обрабатываться так, как если бы они были хешеными. Тем не менее, эта хеш-функция использует идентичность для не подлежащих обработке объектов, а это означает, что два равных объекта, которые оба не подлежат обработке, не будут работать. Я предлагаю вам переопределить это и изменить его на использование хэша эквивалентного изменяемого типа (например, использование hash(tuple(my_list))
if my_list
is is list).
Я также сделал два решения. Другое решение, которое поддерживает порядок элементов, используя подкласс OrderedDict и Counter, который называется OrderedCounter. Теперь вот функции:
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 - неупорядоченная сортировка, oremd - упорядоченная сортировка. Вы можете четко сказать, какой из них быстрее, но я все равно объясню. Неупорядоченная сортировка немного быстрее. Он хранит меньше данных, так как не нуждается в порядке.
Теперь я также хотел показать сравнение скорости каждого ответа. Итак, я сделаю это сейчас.
Какая функция самая быстрая?
Для удаления дубликатов я собрал 10 функций из нескольких ответов. Я рассчитал скорость каждой функции и поместил ее в график, используя matplotlib.pyplot .
Я разделил это на три этапа построения графиков. Хэшируемый - это любой объект, который может быть хэширован, а неэхируемый - это любой объект, который не может быть хеширован. Упорядоченная последовательность - это последовательность, которая сохраняет порядок, неупорядоченная последовательность не сохраняет порядок. Теперь, вот еще несколько терминов:
Unordered Hashable был для любого метода, который удалял дубликаты, которые не обязательно должны поддерживать порядок. Это не должно было работать на непоправимые последствия, но могло.
Ordered Hashable предназначался для любого метода, который сохранял порядок элементов в списке, но он не должен был работать для непоправимых предметов, но мог.
Ordered Unhashable - это любой метод, который сохраняет порядок элементов в списке и работает на непоправимые убытки.
На оси Y указано количество секунд, которое потребовалось.
На оси абсцисс - номер, к которому была применена функция.
Мы сгенерировали последовательности для неупорядоченных хеш-хэлов и упорядоченных хеш-хеллов со следующим пониманием: [list(range(x)) + list(range(x)) for x in range(0, 1000, 10)]
Для заказанных небрежных предметов: [[list(range(y)) + list(range(y)) for y in range(x)] for x in range(0, 1000, 10)]
Обратите внимание, что в диапазоне есть «шаг», потому что без него это заняло бы 10x больше времени. Кроме того, потому что, по моему личному мнению, я думал, что это могло бы выглядеть немного легче для чтения.
Также обратите внимание, что ключи на легенде - это то, что я пытался угадать как наиболее важные части функции. Что за функцию выполняет худший или лучший? График говорит сам за себя.
С этим улажено, вот графики.
Неупорядоченные хешаблы
(Увеличено)
Заказал Hashables
(Увеличено)
Заказано Небрежно
(Увеличено)