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 и реализовать его как обычный список срезов (но затем вы должны предоставить кортеж среза или объект среза.)