Лучший способ создать «перевернутый» список в Python? - PullRequest
80 голосов
/ 14 сентября 2010

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

Вот одно решение, которое мне пришло в голову:

new_list = list(reversed(old_list))

Также возможно дублировать old_list и затем повернуть вспятьдубликат на месте:

new_list = list(old_list) # or `new_list = old_list[:]`
new_list.reverse()

Есть ли лучший вариант, который я упустил?Если нет, есть ли веская причина (например, эффективность) использовать один из вышеперечисленных подходов над другим?

Ответы [ 3 ]

190 голосов
/ 14 сентября 2010
newlist = oldlist[::-1]

Разделение [::-1] (которое моя жена Анна любит называть «марсианский смайлик» ;-) означает: вырезать всю последовательность с шагом -1, т. Е. Наоборот.Это работает для всех последовательностей.

Обратите внимание, что это ( и альтернативы, которые вы упомянули) эквивалентно "мелкой копии", т.е.мутации в элементах, содержащихся в исходном списке, также находятся в элементах в обратном списке, и наоборот.Если вам нужно этого избежать, единственным подходящим вариантом является copy.deepcopy (хотя это всегда потенциально дорогостоящая операция), за которым в этом случае следует .reverse.

51 голосов
/ 14 сентября 2010

Теперь давайте timeit. Подсказка: Alex's [::-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

Обновление: Добавлен метод компоновки списка, предложенный inspectorG4dget.Я позволю результатам говорить сами за себя.

7 голосов
/ 13 мая 2013

Корректировки

Стоит предоставить базовый тест / корректировку для расчета времени по 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 usecs

...