列表值交换:正确的顺序是什么?为什么?

时间:2018-11-15 17:22:49

标签: python

对于整数列表,例如A = [2, 10, -5],我得到了错误

Traceback (most recent call last):
  File "so.py", line 6, in <module>
    v, A[v-1] = A[v-1], v
IndexError: list assignment index out of range

代码:

for i, v in enumerate(A):
    while 1<=v<=len(A) and v != A[v-1]:
        v, A[v-1] = A[v-1], v

但这可行:

for i, v in enumerate(A):
    while 1<=v<=len(A) and v != A[v-1]:
        A[v-1], v = v, A[v-1]

为什么交换元素的顺序在这里很重要?始终会检查v是否处于绑定状态。

足够奇怪的是无法重现一个较小的示例。但, A = [6, 5, 4, 3, 2] 变成无限循环。

3 个答案:

答案 0 :(得分:7)

Python按照提供的顺序交换变量,因此v被分配了A[v-1]的值,然后尝试重新分配A[v-1]-但由于v已被修改为列表元素v-1超出了A的范围。

答案 1 :(得分:2)

我用[2,10,-5]复制了此内容。 详细的操作顺序是

i, v = 0, 2
1 <= 2 ?     OK
2 != A[1] ?  OK ... stay in loop
    v, A[v-1] = 10, 2
    # This assignment breaks into ...
    v = 10
    A[10-1] = 2
    # ... and this second assignment is out of range.

如果您切换分配顺序:

    A[v-1], v = 2, 10
    # This assignment breaks into ...
    A[2-1] = 2
    v = 10

在这种情况下,您的while条件已经妥善保护了法律转让。

请注意,您不是交换列表值; v是局部变量;它不是对A [i]的引用。例如,在上面的示例中,您确实获得了v=10,但这确实不会影响A [0]的值。

答案 2 :(得分:0)

A = [6, 5, 4, 3, 2]

for i, v in enumerate(A):
    while 1<=v<=len(A) and v != A[v-1]:
        v, A[v-1] = A[v-1], v

您需要尝试用尽您的算法:

开始:

i = 0,v = 6

v(6)不在1到5之间:下一次迭代

i = 1,v = 5,A [5-1] = 2

5在1到5之间; v不等于2:swap-> v = 2; A [4] = 2

i = 1,v = 2,A [2-1] = 5

2在1到5之间; v不等于5:swap-> v = 5; A [1] = 5

i = 1,v = 5,A [5-1] = 2

5在1到5之间; v不等于2:swap-> v = 2; A [4] = 2

i = 1,v = 2,A [2-1] = 5

2在1到5之间; v不等于5:swap-> v = 5; A [1] = 5

...以及不断的

我认为您的算法没有道理。目前尚不清楚为什么要在循环中使用列表中的值来索引列表。我认为对索引和值的这种混淆是您问题的根源。