在python中旋转列表最有效的方法是什么? 现在我有这样的东西:

>>> def rotate(l, n):
...     return l[n:] + l[:n]
... 
>>> l = [1,2,3,4]
>>> rotate(l,1)
[2, 3, 4, 1]
>>> rotate(l,2)
[3, 4, 1, 2]
>>> rotate(l,0)
[1, 2, 3, 4]
>>> rotate(l,-1)
[4, 1, 2, 3]

有没有更好的办法?


当前回答

这也取决于您是想将列表移到合适的位置(改变它),还是想让函数返回一个新列表。因为,根据我的测试,像这样的东西比你的实现(添加两个列表)至少快20倍:

def shiftInPlace(l, n):
    n = n % len(l)
    head = l[:n]
    l[:n] = []
    l.extend(head)
    return l

事实上,即使在它的顶部添加l = l[:]来操作传入的列表的副本,速度仍然是原来的两倍。

各种实现,在http://gist.github.com/288272上有一些计时

其他回答

另一个选择:

def move(arr, n):
    return [arr[(idx-n) % len(arr)] for idx,_ in enumerate(arr)]

可能更适合使用ringbuffer。它不是一个列表,尽管出于您的目的,它的行为可能足够像一个列表。

问题是列表上移位的效率是O(n),这对于足够大的列表来说非常重要。

在环缓冲区中移动只是更新了头的位置也就是O(1)

Jon Bentley在Programming Pearls(第2专栏)中描述了一个优雅而高效的算法,用于将n元素向量x向左旋转i个位置:

让我们把这个问题看作是把数组ab转换成数组 Ba,但我们也假设我们有一个函数,它与 数组的指定部分中的元素。从ab开始 反转a得到arb,反转b得到 Arbr,然后反转整个 得到(arbr)r, 就是。这将产生以下代码 旋转: 反向张(0) 反向(n - 1),我 反向(0,n - 1)

这可以被翻译成Python:

def rotate(x, i):
    i %= len(x)
    x[:i] = reversed(x[:i])
    x[i:] = reversed(x[i:])
    x[:] = reversed(x)
    return x

演示:

>>> def rotate(x, i):
...     i %= len(x)
...     x[:i] = reversed(x[:i])
...     x[i:] = reversed(x[i:])
...     x[:] = reversed(x)
...     return x
... 
>>> rotate(list('abcdefgh'), 1)
['b', 'c', 'd', 'e', 'f', 'g', 'h', 'a']
>>> rotate(list('abcdefgh'), 3)
['d', 'e', 'f', 'g', 'h', 'a', 'b', 'c']
>>> rotate(list('abcdefgh'), 8)
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
>>> rotate(list('abcdefgh'), 9)
['b', 'c', 'd', 'e', 'f', 'g', 'h', 'a']

如果你只想遍历这些元素集,而不是构造一个单独的数据结构,可以考虑使用迭代器来构造一个生成器表达式:

def shift(l,n):
    return itertools.islice(itertools.cycle(l),n,n+len(l))

>>> list(shift([1,2,3],1))
[2, 3, 1]

如果效率是你的目标,(周期?内存?),您最好查看数组模块:http://docs.python.org/library/array.html

数组没有列表的开销。

就纯粹的列表而言,你所拥有的就是你所希望做的。