Python:使数组的最后一项成为第一项

时间:2012-10-11 17:23:01

标签: python list

这是一个非常简单的问题,但我似乎无法找到令人满意的答案。

在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]

但这看起来不正确......“ Pythonic ”,如果你可以

提前谢谢。

4 个答案:

答案 0 :(得分:12)

切片比这更聪明;您可以使用否定索引从最后开始计算:

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

答案 1 :(得分:8)

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]

答案 2 :(得分:8)

你可能想看一下deque,如果你做了很多这些,那就是优化(记忆明智)来做你所要求的。

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

答案 3 :(得分:0)

如果您只需要转储任意访问的列表,正如您在@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对象替换函数中的范围,并将其实现为常规列表切片(但是您已经提供了切片元组或切片对象。)

相关问题