Лучший способ создать "перевернутый" список в Python?
В Python лучший способ создать новый список, элементы которого такие же, как у другого списка, но в обратном порядке? (Я не хочу изменять существующий список на месте.)
Вот одно из решений, которое произошло со мной:
new_list = list(reversed(old_list))
Можно также дублировать old_list
, а затем отменить дубликат:
new_list = list(old_list) # or `new_list = old_list[:]`
new_list.reverse()
Есть ли лучший вариант, который я забыл? Если нет, есть ли веская причина (например, эффективность) использовать один из вышеуказанных подходов над другим?
Ответы
Ответ 1
newlist = oldlist[::-1]
Нарезка [::-1]
(которую моя жена Анна любит называть "марсианским смайлом";-) означает: разрезать всю последовательность с шагом -1, т.е. наоборот. Он работает для всех последовательностей.
Обратите внимание, что это (и упомянутые вами альтернативы) эквивалентно "мелкой копии", то есть: если элементы изменяемы и вы вызываете на них мутаторы, мутации в элементах, хранящихся в исходном списке, также находятся в пункты в обратном списке и наоборот. Если вам нужно избегать этого, то copy.deepcopy
(хотя и всегда потенциально дорогостоящая операция), в этом случае используется .reverse
, является единственным хорошим вариантом.
Ответ 2
Теперь timeit
. Подсказка: Alex [::-1]
самый быстрый:)
$ p -m timeit "ol = [1, 2, 3]; nl = list(reversed(ol))"
100000 loops, best of 3: 2.34 usec per loop
$ p -m timeit "ol = [1, 2, 3]; nl = list(ol); nl.reverse();"
1000000 loops, best of 3: 0.686 usec per loop
$ p -m timeit "ol = [1, 2, 3]; nl = ol[::-1];"
1000000 loops, best of 3: 0.569 usec per loop
$ p -m timeit "ol = [1, 2, 3]; nl = [i for i in reversed(ol)];"
1000000 loops, best of 3: 1.48 usec per loop
$ p -m timeit "ol = [1, 2, 3]*1000; nl = list(reversed(ol))"
10000 loops, best of 3: 44.7 usec per loop
$ p -m timeit "ol = [1, 2, 3]*1000; nl = list(ol); nl.reverse();"
10000 loops, best of 3: 27.2 usec per loop
$ p -m timeit "ol = [1, 2, 3]*1000; nl = ol[::-1];"
10000 loops, best of 3: 24.3 usec per loop
$ p -m timeit "ol = [1, 2, 3]*1000; nl = [i for i in reversed(ol)];"
10000 loops, best of 3: 155 usec per loop
Обновление: Добавлен метод списка list, предложенный inspectorG4dget. Я дам результаты говорить сами за себя.
Ответ 3
корректировок
Стоит предоставить базовый контрольный показатель/корректировку для вычислений timeit от sdolan, которые показывают производительность "полностью измененного" без часто ненужного преобразования list()
. Эта операция list()
добавляет дополнительные 26 usecs к среде выполнения и необходима только в том случае, если итератор недопустим.
Результаты:
reversed(lst) -- 11.2 usecs
list(reversed(lst)) -- 37.1 usecs
lst[::-1] -- 23.6 usecs
Расчеты:
# I ran this set of 100000 and came up with 11.2, twice:
python -m timeit "ol = [1, 2, 3]*1000; nl = reversed(ol)"
100000 loops, best of 3: 11.2 usec per loop
# This shows the overhead of list()
python -m timeit "ol = [1, 2, 3]*1000; nl = list(reversed(ol))"
10000 loops, best of 3: 37.1 usec per loop
# This is the result for reverse via -1 step slices
python -m timeit "ol = [1, 2, 3]*1000;nl = ol[::-1]"
10000 loops, best of 3: 23.6 usec per loop
Выводы:
Вывод этих тестов reversed()
быстрее, чем срез [::-1]
на 12,4 пользователя