Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swaping two elements in a list shows unexpected behaviour

I have a list:

lis = [12,45,15,67,89]

I want to swap 12 and 89 such that the list should look

lis = [89,45,15,67,12]

When I do it this way

lis[0], lis[lis.index(89)] = lis[lis.index(89)], lis[0]

Nothing is changed

lis = [12,45,15,67,89]

But when I do it this way

lis5[0], lis5[4] = lis5[4], lis5[0]

It works perfect

lis = [89,45,15,67,12]

So why it isn't working the first way? PS-The whole reason I want to do the first way is because I want to find the max element in a list and then swap it with the first element of the list.

Something like:

max1 = max(lis)
lis[0], lis[lis.index(max1)] = lis[lis.index(max1)], lis[0]
like image 480
Souvik Ray Avatar asked Jul 02 '17 03:07

Souvik Ray


2 Answers

In short, lis.index(max1) in left/right sides are evaluated at different times; then evaluated to different values (0 for the left side, 4 for the right side).


a, b = b, a

Above statement:

  • creates (b, a) tuple
  • unpacks the above tuple to a and b
    • a = old-value-of-b
    • b = old-value-of-a

lis[0], lis[lis.index(89)] = lis[lis.index(89)], lis[0]

becomes

lis[0], lis[lis.index(89)] = lis[4], lis[0]

=>

lis[0], lis[lis.index(89)] = 89, 0

=>

lis[0] = 89
lis[lis.index(89)] = 0

=>

lis[0] = 89
lis[0] = 0    # NOTE lis.index(89) == 0  at this point

So lis[0] assigned 89, then assigned original value 0 back. => (only the first element changed, and re-assigned original value)


To avoid this problem, assign the index before the swap statement:

idx = lis.index(89)
lis[0], lis[idx] = lis[idx], lis[0]
like image 64
falsetru Avatar answered Oct 13 '22 20:10

falsetru


Just to extend the accepted answer, You can store using dict.

lis = [12,45,15,67,89]
new_list = []


dict = {k:v for (k,v) in enumerate(lis)}

    
dict[0], dict[4] = dict[4], dict[0]
    
for i in range(len(lis)):
    new_list.append(dict[i])
   
print(new_list)

And the way you were trying,

lis = [12,45,15,67,89]

lis[lis.index(89)], lis[0] = lis[0], lis[lis.index(89)]

print(lis) 

both produces,

[89, 45, 15, 67, 12]

[Program finished]

Alternatively, for max values,

lis = [12,45,15,67,89]
max_index = lis.index(max(lis))
lis[0], lis[max_index] = lis[max_index], lis[0]
print(lis) 
like image 32
Subham Avatar answered Oct 13 '22 19:10

Subham