Python: сделать последний элемент массива первым
Это очень простой вопрос, но я, похоже, не смог найти удовлетворительного ответа на него.
каков наилучший способ, в Python, сделать последний элемент списка первым "толкающим" остальную часть списка.
- то, что делает:
>>> a=[1,2,3,4]
>>> a[?????]
[4, 1, 2, 3]
Я знаю, что всегда могу играть с len
, конкатенации списка...
>>> a=[1,2,3,4]
>>> [a[len(a)-1]] + a[0:len(a)-1]
[4, 1, 2, 3]
но это не так... "весть", если можно
спасибо предварительно.
4 ответов
нарезка немного умнее, чем это; вы можете использовать отрицательный индексы для подсчета в конце:
a[-1:] + a[:-1]
демо:
>>> a=[1,2,3,4]
>>> a[-1:] + a[:-1]
[4, 1, 2, 3]
это работает для произвольного числа элементов, которые должны быть перемещены на фронт:
>>> a[-2:] + a[:-2]
[3, 4, 1, 2]
использование нарезки, как это сопоставимо по скорости с использованием .insert()
+ .pop()
(короткий список):
>>> timeit.timeit('a[-1:] + a[:-1]', 'a=[1,2,3,4]')
0.59950494766235352
>>> timeit.timeit('a.insert(0,a.pop(-1))', 'a=[1,2,3,4]')
0.52790379524230957
но выигрывает руки вниз, если вам нужно перенести более одного элемента:
>>> timeit.timeit('a[-2:] + a[:-2]', 'a=[1,2,3,4]')
0.58687901496887207
>>> timeit.timeit('a.insert(0,a.pop(-1));a.insert(0,a.pop(-1))', 'a=[1,2,3,4]')
1.0615170001983643
In [103]: a=[1,2,3,4]
In [104]: a.insert(0,a.pop(-1)) # pop(-1) removes the last element
# and use insert() to insert the popped
# element at 0th endex
In [105]: a
Out[105]: [4, 1, 2, 3]
вы можете посмотреть на очереди, которые оптимизированы (память мудрая), чтобы сделать то, что вы просите, если вы делаете много из них.
from collections import deque
>>> a = deque([1,2,3,4])
>>> a.rotate(1)
... deque([4, 1, 2, 3])
Так как мы делаем timeit
сравнить...
>>> setup = """from collections import deque
a = deque([1,2,3,4])"""
>>> print timeit.timeit('a.rotate(1)', setup=setup)
... 0.219103839131
Если вам просто нужно сбросить список произвольного доступа, как вы упомянули в комментарии к @kreativitea, повторное упорядочение может даже не потребоваться, и вместо этого вы можете создать генератор произвольного доступа:
size = 10
l = range(size)
# use a generator expression to yield slices of the list according
# to your own order.
# note that no error checking is enforced, and that overlapping
# and invalid accessRanges will work, so depending on the usage
# you have for this function, you might want to add some
# sanity checks, like ensuring no overlap between accessRanges
# and that each item is accessed only once.
def ArbitraryListAccessor(listObj, accessRanges):
for ar in accessRanges:
for item in listObj[ar[0]:ar[1]]:
yield item
# to dump the access-ordered list generator as a real list, you need to
# iterate over it, for example, with a list comprehension:
[i for i in ArbitraryListAccessor(l, ((-1,None), (0,-1)))]
# [9, 0, 1, 2, 3, 4, 5, 6, 7, 8]
это медленнее, чем deque, но быстрее, чем создание новых списков. Для нескольких итераций он примерно в два раза медленнее, чем deque, но для одного запуска (например, просто прочитайте список один раз в произвольном порядке) он сопоставим (например, порядок микросекунды.)
преимущество здесь в том, что вы можете определить любые диапазоны произвольного доступа, которые хотите использовать. Вы также можете заменить диапазоны в функции Slice
objects и реализовать его как обычный список срезов (но затем вы должны предоставить кортеж среза или объект среза.)