Carnivorex2
Carnivorex2

Reputation: 13

How to mutate list permanently?

def deep_reverse(L) :
    for i in range (len(L)-1,-1,-1):
        L=L[::-1]
    for i in range (len(L)-1,-1,-1):
        L[i]=L[i][::-1]  

L = [[0, 1, 2], [1, 2, 3], [3, 2, 1], [10, -10, 100]]
deep_reverse(L) 
print(L)

So I have this code here and a function called deep_reverse(L). I am trying to mutate the list L, at the end when i print(L) it prints out L = [[0, 1, 2], [1, 2, 3], [3, 2, 1], [10, -10, 100]]. However, when I print from within the function, I get L= [[2, 1, 0], [3, 2, 1], [1, 2, 3], [100, -10, 10]], which is what I want. How can i permanently mutate L so that it stays that way when I print it outside the function.

Upvotes: 0

Views: 648

Answers (4)

aneroid
aneroid

Reputation: 15962

You've said that if L = [[0, 1, 2], [1, 2, 3], [3, 2, 1], [10, -10, 100]] you
want the result L = [[2, 1, 0], [3, 2, 1], [1, 2, 3], [100, -10, 10]].

Based on Barmar's answer, you can do this:

def deep_reverse(L):
    for subL in L:
        subL[:] = subL[::-1]


>>> L = [[0, 1, 2], [1, 2, 3], [3, 2, 1], [10, -10, 100]]
>>> deep_reverse(L)
>>> L
[[2, 1, 0], [3, 2, 1], [1, 2, 3], [100, -10, 10]]

Upvotes: 0

Barmar
Barmar

Reputation: 780984

You're not mutating anything. The function creates a new list and assigns it back to the local variable, which has no effect on the caller's variable.

Also, your first for loop is repeatedly reversing L. If the list has an even number of elements, it will reverse it back to the original order.

Use slice assignment to modify the list in place.

def deep_reverse(L):
    L[:]=L[::-1]
    for i in range (len(L)-1,-1,-1):
        L[i][:]=L[i][::-1] 

Note also that your code only reverses two levels deep. Use recursion to handle any depth.

def deep_reverse(L):
    if isinstance(L, list):
        L[:] = L[::-1]
        for subL in L:
            deep_reverse(subL)

Upvotes: 2

Daniel Hao
Daniel Hao

Reputation: 4980

It as simple as do this - it's to minimize the changes of your code: (remove first loop- since no effect; and add return statement) all in-placed change.

def deep_reverse(L):
    for i in range(len(L)-1, -1, -1):
        L[i] = L[i][::-1]
        
    return L


L = [[0,1,2], [1,2,3], [3,2,1], [10,-10,100]]

LL = deep_reverse(L)

print(LL)  # [[2, 1, 0], [3, 2, 1], [1, 2, 3], [100, -10, 10]]

Upvotes: 0

Oskar
Oskar

Reputation: 1460

The problem is that by calling L = L[::-1] you allocate a new array for L and do not overwrite the one you passed on to the function. In order to do this you need to use assign the new value as L[:] = L[::-1].

Thus your function becomes:

def deep_reverse(L):
    L[:] = L[::-1]
    for i in range (len(L)-1,-1,-1):
        L[i] = L[i][::-1]


L = [[0, 1, 2], [1, 2, 3], [3, 2, 1], [10, -10, 100]]
deep_reverse(L) 
print(L) # [[100, -10, 10], [1, 2, 3], [3, 2, 1], [2, 1, 0]]

Furthermore, I assumed you wanted the single elements to be reversed, so you don't need the first for loop.

Upvotes: 0

Related Questions