在python中重新定位子列表的最快方法

TTT*_*TTT 9 python list

从Python中的列表重新定位子列表的最快方法是什么?

假设我们有一个列表L = [a,b,c,d,e,f,g,h],现在我想把[c,d,e]g放在列表中.我怎么能快速做到这一点?

编辑:换句话说,我想写一个函数:

  1. 从L中提取长度为n的子列表L_sub ,留下L_temp
  2. 将L_sub的项目在给定位置i插入L_temp

我猜的主要问题是如何尽快将列表插入列表.

Lau*_*low 5

我认为OP想要在这里做到这一点.

快速操作的关键是最小化列表的创建和列表的缩短/延长.这意味着我们必须努力始终对列表索引进行1:1的分配,所以不L[i:i] = L[a:b],不L[a:b] = [].使用具有循环insertpop更差,因为这样你缩短和延长列表很多次.连接列表也很糟糕,因为您首先必须为每个部分创建一个列表,然后创建更大和更大的连接列表,每个列表一次+.由于您希望"就地"执行此操作,因此您必须最终分配生成的列表L[:].

    # items:   0 | 1   2   3 | 4   5   6   7 | 8   9
    #            a   span1   b     span2     c
    # pos:       1           4               8

    # Result:
    #          0 | 4   5   6   7 | 1   2   3 | 8   9
    #            a     span2         span2   c
Run Code Online (Sandbox Code Playgroud)

让我们先做一个观察.如果a = start,b = end = start + length和,c是插入位置,那么我们希望做的操作是切割|标记并交换span1span2.但是,如果b = startc = enda是插入位置,那么我们想交换span1span2.所以在我们的函数中,我们只处理必须交换的两个连续段.

我们无法完全避免制作新列表,因为我们需要在移动内容时存储重叠值.但是,我们可以通过选择要存储到临时列表中的两个跨区中的哪一个使列表尽可能短.

def inplace_shift(L, start, length, pos):
    if pos > start + length:
        (a, b, c) = (start, start + length, pos)
    elif pos < start:
        (a, b, c) = (pos, start, start + length)
    else:
        raise ValueError("Cannot shift a subsequence to inside itself")
    if not (0 <= a < b < c <= len(L)):
        msg = "Index check 0 <= {0} < {1} < {2} <= {3} failed."
        raise ValueError(msg.format(a, b, c, len(L)))

    span1, span2 = (b - a, c - b)
    if span1 < span2:
        tmp = L[a:b]
        L[a:a + span2] = L[b:c]
        L[c - span1:c] = tmp
    else:
        tmp = L[b:c]
        L[a + span2:c] = L[a:b]
        L[a:a + span2] = tmp
Run Code Online (Sandbox Code Playgroud)

科斯似乎在他的时间上犯了一个错误,所以我在纠正参数(endstart和计算length)后用他的代码重新编写它们,这些是从最慢到最快的结果.

Nick Craig-Wood: 100 loops, best of 3: 8.58 msec per loop 
vivek: 100 loops, best of 3: 4.36 msec per loop
PaulP.R.O. (deleted?): 1000 loops, best of 3: 838 usec per loop
unbeli: 1000 loops, best of 3: 264 usec per loop
lazyr: 10000 loops, best of 3: 44.6 usec per loop
Run Code Online (Sandbox Code Playgroud)

我没有测试任何其他方法产生正确的结果.