Я пытаюсь взять list
(orig_list
ниже) и вернуть list
(new_list
ниже), который:
Вот что я до сих пор, что кажется... Я собираюсь сказать "странно", хотя я уверен, что есть лучший способ сказать это. Я в основном откладываю, используя list()
дважды для того, что кажется довольно простым, и тогда мне интересно об эффективности этого подхода.
new_list = list(reversed(sorted(list(set(orig_list)))))
Вопрос № 1 (вопрос в стиле SO):
Правильны ли следующие предложения?
list
чем преобразовать list
в set
и обратно.Вопрос №2 (бонус):
Есть ли способы добиться того же результата в меньшем количестве Os, или использовать менее подробный подход? Если да, то какой из них является примером (-ами)?
sorted(set(orig_list), reverse=True)
Самый короткий код, более эффективный, тот же результат.
В зависимости от размера, он может или не может быть быстрее отсортировать сначала, затем дедупую в линейном времени, как пользователь2864740 предлагает в комментариях. (Самый большой недостаток этого подхода - это полностью на Python, в то время как вышеприведенная строка выполняется в основном в собственном коде.)
Ваши вопросы:
Вам не нужно конвертировать из набора в список и обратно. sorted
принимает любую итерацию, так квалифицирует набор, и выкладывает список, так что не требуется никакое последующее преобразование.
reversed(sorted(x))
не эквивалентно sorted(x, reverse=True)
. Вы получаете тот же результат, но медленнее - sort
имеет одинаковую скорость, будь то прямая или обратная, поэтому reversed
- это добавление дополнительной операции, которая не нужна, если вы отсортируете ее до правильного упорядочения с самого начала.
Здесь у вас есть несколько расточительных шагов, но ваше предложение в основном правильное. Единственные реальные улучшения, которые нужно сделать, - избавиться от всех ненужных временных list
s:
new_list = sorted(set(orig_list), reverse=True)
sorted
уже преобразует свой вход в list
(поэтому нет необходимости list
ify перед переходом к sorted
), и вы можете заставить его напрямую создавать list
отсортированный в обратном порядке (поэтому нет необходимости создавать list
только чтобы сделать его копию в задний ход).
Единственное возможное улучшение в режиме большого времени - если вы знаете, что данные уже отсортированы, и в этом случае вы можете избежать сортировки 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
не очень практично для изначально несортированных входных данных, потому что, если дубликаты даже отдаленно распространены, удаление их посредством uniquification как шаг O(n)
почти всегда стоит того, что уменьшает n
в более дорогостоящем O(n log n)
шаг сортировки. groupby
также является относительно медленным инструментом; характер реализации, используя кучу временных итераторов для каждой группы, внутреннее кэширование значений и т.д., означает, что на практике это медленнее O(n)
чем O(n)
-эквивалентность через set
, причем основным преимуществом является (делая его масштабируемым для наборов данных, передаваемых с диска или сети и обратно, без сохранения чего-либо в течение длительного времени, когда set
должен вытащить все в память).
Другая причина использовать sorted
+ groupby
была бы, если бы ваши данные не были хешируемыми, но были сопоставимы; в этом случае set
не является вариантом, поэтому единственный выбор - сортировка и группировка.
groupby
кажется groupby
из-за использования «Обычно» .. (в C # или SQL, в качестве контрпримера, я бы ожидал «группа по» для работы с несортированными данными так же хорошо)
groupby
аналогичен uniq
из groupby
GNU, это не комбинированный шаг сортировки + группировки, как в SQL. Тот факт, что он не сортируется, на самом деле полезен в некоторых случаях (для группировки прогонов данных в порядке их появления), поэтому они говорят «обычно», но, как и в случае с uniq
, вам обычно нужно предшествовать с сортировкой если вам нужна только одна группа для каждого уникального ключа на протяжении всей итерации.