Search code examples
pythonlistswap

How to swap items in a list within a list python


I am trying to randomly swap 2 items in each list within a list, where those to be swapped are not in another list.

Here is my code

import random    


def swap(mylist):
        remain = [[1, 2], [4], [], [8, 2], [1, 4], [5, 2, 1], [], [9, 5], [7]]
        for x in range(0, 9):
            remaining = set(mylist[x]) - set(remain[x])
            to_swap = random.sample(remaining, 2)
            mylist[x][mylist[x].index(to_swap[0])], mylist[x][mylist[x].index(to_swap[1])] = mylist[x][mylist[x].index(to_swap[1])], mylist[x][mylist[x].index(to_swap[0])]
        return mylist


print(swap([[8, 5, 4, 1, 3, 9, 7, 6, 2], [9, 3, 5, 6, 4, 7, 1, 2, 8], [7, 3, 2, 5, 4, 1, 9, 6, 8], [2, 1, 3, 8, 6, 9, 5, 7, 4], [1, 2, 3, 5, 7, 4, 9, 8, 6], [6, 9, 3, 1, 7, 4, 2, 8, 5], [1, 2, 7, 4, 3, 8, 5, 9, 6], [3, 7, 8, 4, 1, 5, 9, 6, 2], [4, 2, 6, 5, 7, 1, 9, 3, 8]]))

Whenever I run this and print out the result, it just prints out my input again.

Does anyone know what is wrong with my code?

Thanks.


Solution

  • Your code performs the swaps with about one half of the sublists. I wonder what the reason of this behavior is *(see below).

    If you rewrite the swapping part like this:

        i = mylist[x].index(to_swap[0])
        j = mylist[x].index(to_swap[1])
        mylist[x][i], mylist[x][j] = mylist[x][j], mylist[x][i]
    

    then it works.

    UPDATE:

    There is no need to access the lists on the right-hand side of the assignment, since we already know the values, so the updated answer would be:

        i = mylist[x].index(to_swap[0])
        j = mylist[x].index(to_swap[1])
        mylist[x][i], mylist[x][j] = to_swap[1], to_swap[0]
    

    *UPDATE 2:

    The above mentioned behavior is caused by the fact that in multiple assignments, expressions on the left-hand side are evaluated one by one from left to right. That means the OP's code didn't work in cases where index(to_swap[0]) < index(to_swap[1]).

    Example: values 5 and 6 in the first sublist [8, 5, 4, 1, 3, 9, 7, 6, 2]. First, the program will do

    mylist[x][mylist[x].index(5)] = 6
    

    modifying the list to [8, 6, 4, 1, 3, 9, 7, 6, 2]. Second, the program will do

    mylist[x][mylist[x].index(6)] = 5
    

    modifying it back to [8, 5, 4, 1, 3, 9, 7, 6, 2].