I am having trouble understanding what's happening behind the scenes for this simple code snippet:
def changeArray(arr):
for i in range(len(arr)):
arr[i], arr[arr[i] - 1] = arr[arr[i] - 1], arr[i]
print(arr)
return(arr)
The code assumes the array has as its elements the integers from 1 to n. The output for the given code when the input is [1,3,4,2] is:
[1, 3, 4, 2]
[1, 4, 4, 3]
[1, 4, 4, 3]
[1, 4, 4, 3]
Out[8]: [1, 4, 4, 3]
while I was expecting it to print and return this:
[1, 3, 4, 2]
[1, 4, 3, 2]
[1, 4, 3, 2]
[1, 2, 3, 4]
Out[8]: [1, 2, 3, 4]
Why are the values changing at all when the code is only swapping elements?
Edit:
It turns out, changing the swapping order fixes the problem:
def changeArray(arr):
for i in range(len(arr)):
arr[arr[i]-1], arr[i] = arr[i], arr[arr[i]-1]
print(arr)
return(arr)
This gives the following output:
[1, 3, 4, 2]
[1, 4, 3, 2]
[1, 4, 3, 2]
[1, 2, 3, 4]
Out[8]: [1, 2, 3, 4]
How did changing the order do the swapping as expected, and the reverse did something else entirely?
In general, you shouldn't use the object you're mutating to specify the target positions you want to replace, or it gets very confusing.
When you write this:
arr[i], arr[arr[i] - 1] = arr[arr[i] - 1], arr[i]
It's roughly equivalent to:
tup = arr[arr[i] - 1], arr[i]
x, y = tup
arr.__setitem__(i, x)
arr.__setitem__(arr[i] - 1, y)
(Full details for how to translate this are in the reference docs, but hopefully the inuitive idea is a lot simpler.)
Which should make it clear why you're getting the results you are. And also why all of the following do what you want:
x = arr[i] - 1
arr[i], arr[x] = arr[x], arr[i]
arr[arr[i] - 1], arr[i] = arr[i], arr[arr[i] - 1]
def swap(x, y):
arr[x], arr[y] = arr[y], arr[x]
swap(i, arr[i] - 1)
I think the first one is the simplest (the second one looks simple, but only misleadingly so).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With