在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]
有没有更好的办法?
在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]
有没有更好的办法?
当前回答
对于一个列表X = ['a', 'b', 'c', 'd', 'e', 'f'],并且shift值小于列表长度,我们可以如下所示定义函数list_shift()
def list_shift(my_list, shift):
assert shift < len(my_list)
return my_list[shift:] + my_list[:shift]
的例子,
list_shift (X, 1)返回(' b ', ' c ', ' d ', ' e ', ' f ', ' '] list_shift (X, 3)返回(' d ', ' e ', ' f ', ' ', ' b ', ' c ']
其他回答
deque对两端的拉和推进行了优化。它们甚至有一个专用的rotate()方法。
from collections import deque
items = deque([1, 2])
items.append(3) # deque == [1, 2, 3]
items.rotate(1) # The deque is now: [3, 1, 2]
items.rotate(-1) # Returns deque to original state: [1, 2, 3]
item = items.popleft() # deque == [2, 3]
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 rotatel(nums):
back = nums.pop(0)
nums.append(back)
return nums
对于一个列表X = ['a', 'b', 'c', 'd', 'e', 'f'],并且shift值小于列表长度,我们可以如下所示定义函数list_shift()
def list_shift(my_list, shift):
assert shift < len(my_list)
return my_list[shift:] + my_list[:shift]
的例子,
list_shift (X, 1)返回(' b ', ' c ', ' d ', ' e ', ' f ', ' '] list_shift (X, 3)返回(' d ', ' e ', ' f ', ' ', ' b ', ' c ']
可能更适合使用ringbuffer。它不是一个列表,尽管出于您的目的,它的行为可能足够像一个列表。
问题是列表上移位的效率是O(n),这对于足够大的列表来说非常重要。
在环缓冲区中移动只是更新了头的位置也就是O(1)