Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在python中旋转列表的有效方法_Python_List - Fatal编程技术网

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

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

用例是什么?通常,我们实际上并不需要一个完全移位的数组——我们只需要