Лучший / самый питонный способ удалить дубликаты из списка и отсортировать их в обратном порядке - PullRequest
0 голосов
/ 19 октября 2018

Я пытаюсь взять list (orig_list ниже) и вернуть list (new_list ниже), который:

  • не содержит повторяющихся элементов (т.е.содержит только уникальные элементы)
  • отсортировано в обратном порядке

Вот что у меня есть до сих пор, что кажется ... Я собираюсь сказать "странно", хотя яЯ уверен, что есть лучший способ сказать это.Я в основном откладываю использование list() дважды для того, что кажется довольно простым, и затем я задаюсь вопросом об эффективности этого подхода.

new_list = list(reversed(sorted(list(set(orig_list)))))

Вопрос# 1 (вопрос в стиле SO):

Правильны ли следующие предложения?

  1. Нет более эффективного способа получить уникальные элементы list, чем преобразованиеlist в set и обратно.
  2. Поскольку наборы неупорядочены в Python , необходимо (1) преобразовать в набор перед удалением дублирующих элементов, так как в противном случае вы потеряетесортировать в любом случае, и (2) перед сортировкой необходимо преобразовать обратно в список.
  3. Использование списка (reversed ()) программно эквивалентно использованию list.sort (reversed = True).

Вопрос № 2 (бонус):

Существуют ли способы достижения того же результата при меньшем количестве ОС или использовании менее многословного подхода?Если да, то что это за пример (ы)?

Ответы [ 2 ]

0 голосов
/ 19 октября 2018

У вас здесь есть несколько слегка расточительных шагов, но ваше предложение в значительной степени верно.Единственные реальные улучшения, которые необходимо сделать, - это избавиться от всех ненужных временных list s:

new_list = sorted(set(orig_list), reverse=True)

sorted уже преобразует свои входные данные в list (поэтому нет необходимости listперед переходом к sorted), и вы можете получить его непосредственно для вывода list, отсортированного в обратном порядке (поэтому не нужно создавать list только для того, чтобы сделать его копию в обратном порядке).

Единственное мыслимое улучшение времени big-O - это если вы знаете данные уже отсортированы, и в этом случае вы можете избежать сортировки O(n log n) и выполнить uniqify без потери существующего порядка сортировки на , используяitertools.groupby:

    new_list = [key for key, grp in itertools.groupby(orig_list)]

Если orig_list отсортировано в прямом порядке, вы можете изменить результат без каких-либо затрат, изменив itertools.groupby(orig_list) на itertools.groupby(reversed(orig_list)).

Решение groupby не очень практично для изначально несортированных входов, потому что, если дубликаты распространены даже удаленно, удаление их с помощью уникального кода как шага O(n) почти всегда того стоит, так как уменьшает nв более дорогойу O(n log n) шаг сортировки.groupby также является относительно медленным инструментом;Характер реализации, использующей кучу временных итераторов для каждой группы, внутреннее кэширование значений и т. д., означает, что на практике это медленнее O(n), чем унификация O(n) через set, причем его основным преимуществом являетсяаспект потоковой передачи (масштабирование до наборов данных, передаваемых с диска или из сети и обратно без долгосрочного хранения, где set должно вытянуть все в память).

Другая причина использовать sorted+ groupby было бы, если бы ваши данные не были хэшируемыми, но были сопоставимы;в этом случае set не вариант, поэтому единственный выбор - сортировка и группировка.

0 голосов
/ 19 октября 2018
sorted(set(orig_list), reverse=True)

Самый короткий в коде, более эффективный, тот же результат.

В зависимости от размера, сначала может выполняться сортировка, а может быть и быстрее, а не дедупликация за линейное время, как предлагает пользователь 2864740 в комментариях.(Самым большим недостатком этого подхода является то, что он будет полностью на Python, хотя приведенная выше строка выполняется в основном в нативном коде.)

Ваши вопросы:

  • Вы не делаетенужно конвертировать из набора в список и обратно.sorted принимает любую итерацию, поэтому set квалифицирует и выплевывает список, поэтому постконверсия не требуется.

  • reversed(sorted(x)) равно , а не эквивалентно sorted(x, reverse=True).Вы получаете тот же результат, но медленнее - sort имеет одинаковую скорость как в прямом, так и в обратном направлении, поэтому reversed добавляет дополнительную операцию, которая не требуется, если вы сортируете по порядку с самого начала.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...