我已经研究过在这个网站上的列表中交换元素,但是大多数情况都涉及将一个元素与另一个元素交换。
这里我试图交换长度不等的切片的位置。有关示例列表:
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
的第一个元素的前一个位置。其余部分如下。
有一种简单的方法可以优雅高效地完成这项工作吗?
答案 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
之类的切片。
该函数依赖于以下事实:如果您尝试在此处交换切片a
和c
:
[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]