Разберите следующий фрагмент на Python и опишите, что он делает, в каких случаях он работает неправильно или неэффективно, и как вы бы его улучшили для больших массивов данных: def remove_duplicates(arr): res = []\nfor i in arr:\n if i not in res:\n res.append(i)\nreturn res

10 Окт в 13:31
4 +1
0
Ответы
1

Что делает фрагмент
def remove_duplicatesarrarrarr:
res = for i in arr:
if i not in res:
res.appendiii return res

Возвращает список элементов из arr без повторов, сохраняя порядок первого появления first−seenorderfirst-seen orderfirstseenorder.Проверка "i not in res" использует сравнение по равенству ======.

Проблемы и случаи, когда работает плохо или неправильно

Медленно для больших массивов O(n2)O(n^2)O(n2):

Операция "i not in res" для списка — линейная, поэтому при n элементах получается приблизительно сумма 1..n → On2n^2n2 по времени.Память — Onnn в res, но это ожидаемо.

Поведение с не-хэшируемыми элементами:

Текущий код работает и с не-хэшируемыми элементами например,спискаминапример, спискаминапример,списками, потому что использует список для проверки. Это плюс, но при больших объёмах всё равно медленно.

Специальные случаи равенства:

Некоторые значения например,NaNнапример, NaNнапример,NaN ведут себя нетривиально: float′nan′'nan'nan != float′nan′'nan'nan, это может привести к тому, что «повторы» NaN останутся как несколько элементов.Объекты с переопределённым eq / hash могут давать неожиданные результаты при использовании различных подходов set/dictvsлинейныйпоискset/dict vs линейный поискset/dictvsлинейныйпоиск.

Как улучшить вариантыипримерварианты и примервариантыипример

1) Самый простой и быстрый для хэшируемых элементов сохранениепорядкасохранение порядкасохранениепорядка:

В Python 3.7+ можно сделать:
listdict.fromkeys(arr)dict.fromkeys(arr)dict.fromkeys(arr) это Onnn по времени всреднемв среднемвсреднем, Onnn по памяти. Очень компактно и быстро. Требует, чтобы элементы были хэшируемы.

2) Общий оптимальный подход с учётом смешанных типов хэшируемые+не−хэшируемыехэшируемые + не-хэшируемыехэшируемые+нехэшируемые:

Используем множество для хэшируемых элементов и отдельный список для не-хэшируемых fallbackfallbackfallback. Это даёт Onnn в среднем, а квадратичность остаётся только для не-хэшируемых элементов.
Пример:
def remove_duplicatesarrarrarr:
seen_hashable = set seen_unhashable = res = for x in arr:
try:
if x not in seen_hashable:
seen_hashable.addxxx res.appendxxx except TypeError:
x не хэшируем — fallback if x not in seen_unhashable:
seen_unhashable.appendxxx res.appendxxx

return res

3) Если порядок не важен:

Просто setarrarrarr — Onnn среднее, но порядок теряется.Или: sortedset(arr)set(arr)set(arr) — Onlognn log nnlogn и возвращает упорядоченные элементы.

4) Если данные — Numpy / Pandas:

Для numpy: numpy.uniquearrarrarr естьопцияreturnindexдлясохраненияпорядкапервыхпоявленийесть опция return_index для сохранения порядка первых появленийестьопцияreturni ndexдлясохраненияпорядкапервыхпоявлений.Для pandas: pd.Seriesarrarrarr.drop_duplicates — оптимизировано для больших наборов.

5) Для очень больших данных непомещаютсявпамятьне помещаются в памятьнепомещаютсявпамять:

Варианты:
Внешняя сортировка externalsortexternalsortexternalsort + удаление последовательных дублей.Использование СУБД INSERTIGNORE/UNIQUE−индексINSERT IGNORE / UNIQUE-индексINSERTIGNORE/UNIQUEиндекс.Bloom filter для приближённой дедупликации экономияпамяти,новозможныложныесрабатыванияэкономия памяти, но возможны ложные срабатыванияэкономияпамяти,новозможныложныесрабатывания.

Кратко по сложностям

Исходный код: On2n^2n2 время, Onnn память.dict.fromkeys / set-based: Onnn среднее время, Onnn память требуетхэшируемыхэлементовтребует хэшируемых элементовтребуетхэшируемыхэлементов.Сортировка + groupby: Onlognn log nnlogn время, возможно меньше памяти при внешней сортировке.

Резюме и рекомендация

Для обычных списков хэшируемых объектов используйте listdict.fromkeys(arr)dict.fromkeys(arr)dict.fromkeys(arr) или set-подход с seen — это простой и быстрый вариант.Если встречаются не-хэшируемые объекты — используйте комбинированный подход set+fallbackнасписокset + fallback на списокset+fallbackнасписок.Для очень больших данных применяйте инструменты уровня numpy/pandas, внешнюю сортировку или базу данных; при необходимости приближённого результата рассмотрите bloom filter.
10 Окт в 14:06
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир