How to copy a list to another variable and leave this variable immutable?

164 Views Asked by At

I've maid an algorithm that reverse the diagonals of an array. I'm trying to copy the list a to b immutable.

I tried to use "slices" (b = a[:]), list comprehension and b = a.copy() but the only one that worked was b = copy.deepcopy(a). Are there other ways to get the copy?

import copy
a = [[1,2,3],[4,5,6],[7,8,9]]
b = copy.deepcopy(a)
d = b
c = []

h = len(a[0])-1
x_ptrocar = []

for i in range(len(a)-1):
    if i == h:
        break
    else:
        x_ptrocar.extend([[i,i,h,h],[i,h,h,i],[h,h,i,i],[h,i,i,h]])
        h -=1
for l in range(len(x_ptrocar)):
    for m in range(0,4):
        y_original = x_ptrocar[l][3]
        y_ptrocar = x_ptrocar[l][1]
        x_original = x_ptrocar[l][2]
        x_ptrocarr = x_ptrocar[l][0]
        a[x_original][y_original]=b[x_ptrocarr][y_ptrocar]
print(a)

I expect the output of [[1,2,3],[4,5,6],[7,8,9]] to be [[9,2,7], [4,5,6],[3,8,1]], and it's working for copy.deepcopy, but not for any other method I can find.

1

There are 1 best solutions below

0
On BEST ANSWER

copy.deepcopy is overkill for this, pulling in a module and adding function overhead. Since you have a list of lists, making a copy of the outer list with b = a[:] isn't sufficient because the inner lists in both a and b point to identical objects.

You can use a list comprehension as follows:

b = [x[:] for x in a]

This takes a slice of each list in a, creating a new copy of each sublist without aliasing.


Incidentally, the logic can be simplified somewhat--walk towards the center of the matrix, swapping the top-left/bottom-right and top-right/bottom-left cells along the way:

def reverse_diagonals(m):
    m = [x[:] for x in m]

    for i in range(len(m) // 2):
        m[i][i], m[-i-1][-i-1] = m[-i-1][-i-1], m[i][i]
        m[i][-i-1], m[-i-1][i] = m[-i-1][i], m[i][-i-1]

    return m

This assumes a nxn matrix.