交换不等列表切片的优雅方法?

时间:2017-10-31 22:56:47

标签: python python-3.x list

我已经研究过在这个网站上的列表中交换元素,但是大多数情况都涉及将一个元素与另一个元素交换。

这里我试图交换长度不等的切片的位置。有关示例列表:

x = [6,2,4,3,4,1,4,5]

我希望有一种优雅的方式来交换列表和变量中的值,例如下面的表格:

x[0:1], x[1:7] = x[1:7], x[0:1]

#Expected output
x = [2, 4, 3, 4, 1, 4, 5, 6]

不出所料,它不起作用,它交换了前两个元素:

#Actual output
x = [2, 6, 4, 3, 4, 1, 4, 5]

另一个例子:使用x[0:4]交换x[5:7]

#Expected output
x = [1, 4, 4, 6, 2, 4, 3, 5]

我希望很明显,交换是这样的,slice1的第一个元素占据了slice2的第一个元素的前一个位置。其余部分如下。

有一种简单的方法可以优雅高效地完成这项工作吗?

4 个答案:

答案 0 :(得分:1)

您可以使用collections.deque来旋转值:

import collections
x = [6,2,4,3,4,1,4,5]
d = collections.deque(x)
d.rotate(-1)
print(d)

输出:

[2, 4, 3, 4, 1, 4, 5, 6]

答案 1 :(得分:0)

使用直接切片执行此操作的简单方法是使用直切片连接:

x = [6,2,4,3,4,1,4,5]
x = x[1:] + x[:1]  

print x

输出:

[2, 4, 3, 4, 1, 4, 5, 6]

对于第二种情况,你可以将它分成三部分。

发布失败的分析:

您尝试的分配形式错误:多重赋值是对表达式执行表达式,而不是值的流。您输入的内容分解为并行评估和

的分配
x[0:1] = x[1:7]
x[1:7] = x[0:1]

如果你单独进行这些操作,你会发现在每种情况下,分配仅限于较小的切片。

答案 2 :(得分:0)

我认为没有任何优雅,完全通用的方式。这是一种不那么优雅的方式:

def swapslices(l, from1, to1, from2, to2):
    if not (from1 <= to1 <= from2 <= to2):
        raise ValueError('slices out of order or overlapping')
    if to1 - from1 == to2 - from2:
        # Easy case. No need to shift the part between the two slices.
        l[from1: to1], l[from2, to2] = l[from2: to2], l[from1: to1]
    else:
        # Hard case. We need to rewrite the whole section.
        l[from1: to2] = l[from2: to2] + l[to1: from2] + l[from1: to1]

此功能要求您首先传递下部切片,并且不要尝试使用6:3之类的切片。

该函数依赖于以下事实:如果您尝试在此处交换切片ac

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    ----  ----  -------
      a     b       c

这样做相当于用a + b + c替换整个c + b + a部分:

[0, 5, 6, 7, 3, 4, 1, 2, 8, 9]
    -------  ----  ----
        c      b     a

示例:

>>> l = list(range(10))
>>> swapslices(l, 1, 3, 5, 8)
>>> l
[0, 5, 6, 7, 3, 4, 1, 2, 8, 9]

答案 3 :(得分:0)

我认为这应该足够了:

def swapslices(lst, from1, to1, from2, to2):
    # assumes from1:to1 < from2:to2
    def reverse(l, r):
       r = r - 1
       while l < r:
           lst[l], lst[r] = lst[r], lst[l]
           l += 1
           r -= 1
    reverse(to1, from2)
    reverse(from2, to2)
    reverse(from1, to1)
    reverse(from1, to2)

尝试

a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
swapslices(a, 2, 4, 6, 9)
# a is now [0, 1, 6, 7, 8, 4, 5, 2, 3, 9, 10]