Как лучше всего в Python создать новый список, элементы которого будут такими же, как и в каком-либо другом списке, но в обратном порядке? (Я не хочу изменять существующий список на месте.)
Вот одно решение, которое пришло мне в голову:
new_list = list(reversed(old_list))
Также возможно дублировать, а old_list
затем отменить дубликат на месте:
new_list = list(old_list) # or `new_list = old_list[:]`
new_list.reverse()
Есть ли лучший вариант, который я упустил из виду? Если нет, то есть ли веская причина (например, эффективность) использовать один из вышеуказанных подходов вместо другого?
источник
list(reversed(oldlist))
. За исключением незначительных микро-оптимизации, есть ли основание предпочесть ,[::-1]
чтобыreversed()
?reversed
имеет огромное преимущество, когда вам не нужен список, потому что он не тратит впустую память или время на предварительное его создание. Но когда вам действительно нужен список, использование[::-1]
вместоlist(reversed())
аналогично использованию[listcomp]
вместоlist(genexpr)
.[::-1]
обращая внимания на значение третьего аргумента, я могу предположить, что это означает удаление последнего элемента списка, а не его обратное изменение.reversed(list)
точно указывает, что он делает; он разъясняет свое намерение в смысле «Явное лучше, чем неявное», «Читабельность имеет значение» и «Разрезанное лучше, чем плотное».А теперь давайте
timeit
. Подсказка: у Алекса самый[::-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
Обновление: добавлен метод составления списка, предложенный инспектором G4dget. Пусть результаты говорят сами за себя.
источник
[::-1]
Корректировки
Стоит предоставить базовый тест / корректировку для расчетов timeit с помощью sdolan, которые показывают производительность «обратного» без часто ненужного
list()
преобразования. Этаlist()
операция добавляет к среде выполнения еще 26 мксек и требуется только в том случае, если итератор неприемлем.Полученные результаты:
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 мксек.источник
''.join(reversed(['1','2','3']))
, метод среза все равно на> 30% быстрее.