在python中旋转列表的有效方法
在python中,轮换列表最有效的方法是什么? 现在我有这样的事情:在python中旋转列表的有效方法,python,list,Python,List,在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] >>&
>>> 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]
def shift(seq, n):
shifted_seq = []
for i in range(len(seq)):
shifted_seq.append(seq[(i-n) % len(seq)])
return shifted_seq
print shift([1, 2, 3, 4], 1)
a.append(a.pop(0))
有更好的方法吗?a在两端拉和推都是经过优化的。他们甚至有一个专用的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]
a.append(a.pop(0))
如果效率是您的目标,(周期?内存?),您最好查看阵列模块:
a.append(a.pop(0))
数组没有列表的开销
a.append(a.pop(0))
不过,就纯列表而言,您所拥有的是您希望做的最好的事情。这取决于您这样做时希望发生什么:
>>> shift([1,2,3], 14)
a.append(a.pop(0))
您可能需要更改您的:
def shift(seq, n):
return seq[n:]+seq[:n]
a.append(a.pop(0))
致:
a.append(a.pop(0))
可能一个环形缓冲区更合适。它不是一个列表,尽管出于您的目的,它的行为可能足够像一个列表
a.append(a.pop(0))
问题是列表上的移位效率是O(n),这对于足够大的列表来说非常重要
a.append(a.pop(0))
在ringbuffer中移位只是更新头部位置,即O(1)这还取决于您是否希望将列表移位到位(对其进行变异),或者是否希望函数返回新列表。因为,根据我的测试,类似这样的东西至少比添加两个列表的实现快20倍:
def shiftInPlace(l, n):
n = n % len(l)
head = l[:n]
l[:n] = []
l.extend(head)
return l
a.append(a.pop(0))
事实上,即使在上面添加一个l=l[:]
来操作传入列表的副本,速度仍然是原来的两倍
a.append(a.pop(0))
各种各样的实现,有一定的时间限制,仅仅使用它怎么样
a.append(a.pop(0))
list.pop([i])
a.append(a.pop(0))
删除列表中给定位置的项目,然后将其返回。如果
未指定索引,a.pop()
删除并返回中的最后一项
名单。(方法签名中i
周围的方括号
表示该参数是可选的,而不是您应该键入square
括号位于该位置。您将在中经常看到此符号
Python库参考。)
a.append(a.pop(0))
我将此成本模型作为参考:
a.append(a.pop(0))
a.append(a.pop(0))
切片列表和连接两个子列表的方法是线性时间操作。我建议使用pop,这是一种固定时间操作,例如:
def shift(list, n):
for i in range(n)
temp = list.pop()
list.insert(0, temp)
a.append(a.pop(0))
对于不可变的实现,您可以使用如下内容:
>>> 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]
def shift(seq, n):
shifted_seq = []
for i in range(len(seq)):
shifted_seq.append(seq[(i-n) % len(seq)])
return shifted_seq
print shift([1, 2, 3, 4], 1)
a.append(a.pop(0))
Numpy可以使用以下命令执行此操作:
a.append(a.pop(0))
如果您只想迭代这些元素集合而不是构造单独的数据结构,请考虑使用迭代器构造生成器表达式:
def shift(l,n):
return itertools.islice(itertools.cycle(l),n,n+len(l))
>>> list(shift([1,2,3],1))
[2, 3, 1]
a.append(a.pop(0))
我不知道这是否“有效”,但它也有效:
x = [1,2,3,4]
x.insert(0,x.pop())
a.append(a.pop(0))
编辑:您好,我刚刚发现这个解决方案有一个大问题!
考虑下面的代码:
class MyClass():
def __init__(self):
self.classlist = []
def shift_classlist(self): # right-shift-operation
self.classlist.insert(0, self.classlist.pop())
if __name__ == '__main__':
otherlist = [1,2,3]
x = MyClass()
# this is where kind of a magic link is created...
x.classlist = otherlist
for ii in xrange(2): # just to do it 2 times
print '\n\n\nbefore shift:'
print ' x.classlist =', x.classlist
print ' otherlist =', otherlist
x.shift_classlist()
print 'after shift:'
print ' x.classlist =', x.classlist
print ' otherlist =', otherlist, '<-- SHOULD NOT HAVE BIN CHANGED!'
a.append(a.pop(0))
class MyClass():
定义初始化(自):
self.classlist=[]
def shift_类列表(自身):#右移操作
self.classlist.insert(0,self.classlist.pop())
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
其他列表=[1,2,3]
x=MyClass()
#这是一种神奇的链接被创建的地方。。。
x、 classlist=otherlist
对于xrange中的ii(2):#只需执行两次即可
打印“\n\n\n班次前:”
打印“x.classlist=”,x.classlist
打印“其他列表=”,其他列表
x、 shift_类列表()
打印“班次后:”
打印“x.classlist=”,x.classlist
打印“otherlist=”,otherlist,“我想您正在寻找这个:
a.insert(0, x)
a.append(a.pop(0))
我能想到的最简单的方法是:
a.append(a.pop(0))
以下方法是O(n)到位,具有恒定辅助存储器:
a.append(a.pop(0))
def rotate(arr, shift):
pivot = shift % len(arr)
dst = 0
src = pivot
while (dst != src):
arr[dst], arr[src] = arr[src], arr[dst]
dst += 1
src += 1
if src == len(arr):
src = pivot
elif dst == pivot:
pivot = src
请注意,在python中,这种方法与其他方法相比效率极低,因为它无法利用任何片段的本机实现。我也有类似的情况。例如,要移动两个
a.append(a.pop(0))
def Shift(*args):
return args[len(args)-2:]+args[:len(args)-2]
另一种选择:
a.append(a.pop(0))
def move(arr, n):
return [arr[(idx-n) % len(arr)] for idx,_ in enumerate(arr)]
只是一些关于时间安排的注释:
a.append(a.pop(0))
如果您是从列表开始的,l.append(l.pop(0))
是您可以使用的最快方法。这可以仅通过时间复杂性来显示:
a.append(a.pop(0))
- deque.rotate是O(k)(k=元素数量)
- 列表到数据的转换为O(n)
- list.append和list.pop都是O(1)
因此,如果您从deque
对象开始,您可以deque.rotate()
以O(k)为代价。但是,如果起点是一个列表,则使用deque.rotate()
的时间复杂度为O(n)l.append(l.pop(0)
在O(1)时速度更快
a.append(a.pop(0))
为了便于说明,以下是1M迭代的一些示例计时:
a.append(a.pop(0))
需要类型转换的方法:
a.append(a.pop(0))
deque.使用deque对象旋转
:0.12380790710449219秒(最快)
deque.旋转
并进行类型转换:6.85387894914551秒
np.用nparray滚动
:6.0491721630096436秒
np.滚动
并进行类型转换:27.558452129364014秒
列出此处提到的方法:
a.append(a.pop(0))
l.append(l.pop(0))
:0.3248366937561035秒(最快)
- “
shiftInPlace
”:4.819645881652832秒
使用的正时代码如下
a.append(a.pop(0))
收藏。德克
显示从列表创建DEQUE为O(n):
a.append(a.pop(0))
如果需要创建deque对象,请执行以下操作:
a.append(a.pop(0))
6.85387974914551秒时的1M迭代次数
a.append(a.pop(0))
setup_deque_rotate_with_create_deque = """
from collections import deque
import random
l = [random.random() for i in range(1000)]
"""
test_deque_rotate_with_create_deque = """
dl = deque(l)
dl.rotate(-1)
"""
timeit.timeit(test_deque_rotate_with_create_deque, setup_deque_rotate_with_create_deque)
如果您已经有了deque对象:
a.append(a.pop(0))
1M迭代次数@0.12380790710449219秒
a.append(a.pop(0))
setup_deque_rotate_alone = """
from collections import deque
import random
l = [random.random() for i in range(1000)]
dl = deque(l)
"""
test_deque_rotate_alone= """
dl.rotate(-1)
"""
timeit.timeit(test_deque_rotate_alone, setup_deque_rotate_alone)
np.roll
如果需要创建nParray
a.append(a.pop(0))
1M迭代次数@27.558452129364014秒
a.append(a.pop(0))
setup_np_roll_with_create_npa = """
import numpy as np
import random
l = [random.random() for i in range(1000)]
"""
test_np_roll_with_create_npa = """
np.roll(l,-1) # implicit conversion of l to np.nparray
"""
如果您已经有N阵列:
a.append(a.pop(0))
1M迭代次数@6.0491721630096436秒
a.append(a.pop(0))
setup_np_roll_alone = """
import numpy as np
import random
l = [random.random() for i in range(1000)]
npa = np.array(l)
"""
test_roll_alone = """
np.roll(npa,-1)
"""
timeit.timeit(test_roll_alone, setup_np_roll_alone)
“就地转移”
不需要类型转换
a.append(a.pop(0))
1M迭代次数@4.819645881652832秒
a.append(a.pop(0))
setup_shift_in_place="""
import random
l = [random.random() for i in range(1000)]
def shiftInPlace(l, n):
n = n % len(l)
head = l[:n]
l[:n] = []
l.extend(head)
return l
"""
test_shift_in_place="""
shiftInPlace(l,-1)
"""
timeit.timeit(test_shift_in_place, setup_shift_in_place)
l、 附加(l.pop(0))
不需要类型转换
a.append(a.pop(0))
1M迭代次数@0.3248369637561035
a.append(a.pop(0))
setup_append_pop="""
import random
l = [random.random() for i in range(1000)]
"""
test_append_pop="""
l.append(l.pop(0))
"""
timeit.timeit(test_append_pop, setup_append_pop)
我认为你有最有效的方法
a.append(a.pop(0))
def shift(l,n):
n = n % len(l)
return l[-U:] + l[:-U]
用例是什么?通常,我们实际上并不需要一个完全移位的数组——我们只需要