I'm having trouble with a swapping problem in Python - I want to sort a list of integers by iterating through it and swapping any value that is out of place with the value that should be in that place. I know the input will be an unsorted list of consecutive integers starting from 1, e.g. [4, 3, 1, 2]
sorted = [4, 3, 1, 2]
swapCount = 0
for i in range(len(sorted)):
if sorted[i] != i + 1:
print(f"Before swap {i + 1}: {sorted}")
sorted[i], sorted[sorted.index(i + 1)] = sorted[sorted.index(i + 1)], sorted[i]
swapCount += 1
print(f"After swap {i + 1}: {sorted}")
print(swapCount)
# Before swap 1: [4, 3, 1, 2]
# After swap 1: [4, 3, 1, 2]
# Before swap 2: [4, 3, 1, 2]
# After swap 2: [4, 3, 1, 2]
# Before swap 3: [4, 3, 1, 2]
# After swap 3: [4, 1, 3, 2]
# Before swap 4: [4, 1, 3, 2]
# After swap 4: [2, 1, 3, 4]
# 4
So in my loop, the swap doesn't work (or works in some special cases), while the same syntax works outside a loop:
sorted = [4, 3, 1, 2, 5]
print(sorted)
sorted[0], sorted[2] = sorted[2], sorted[0]
print(sorted)
# [4, 3, 1, 2, 5]
# [1, 3, 4, 2, 5]
Can anyone help me understand what's going wrong in the loop?
An assignment like a, b = c, d
first uses the right-hand side to define a tuple. Then the first element is assigned to a
, and then the second element is assigned to b
. The first assignment may include a side effect that could affect the second; they do not happened simultaneously or independently.
Your code
sorted[i], sorted[sorted.index(i + 1)] = sorted[sorted.index(i + 1)], sorted[i]
is equivalent to
t = sorted[sorted.index(i + 1)], sorted[i]
sorted[i] = t[0]
sorted[sorted.index(i+1)] = t[1]
Note, in particular, that between the two calls to sorted.index
is an assignment that changes sorted
, and thus could cause the second sorted.index
to return a different value than the first.
You want to call sorted.index(i+1)
first and save its value, then use the saved value in the swap.
j = sorted.index(i+1)
sorted[i], sorted[j] = sorted[j], sorted[i]