abhinavm93
abhinavm93

Reputation: 152

Why is my original 2D array being modified in the following code

Im trying to solve a coding problem where i have to generate some matrices, im new to python and i cant figure out why my matrix keeps getting changed to the latest matrix being generated. Here's the code i have so far:

def mirrorHorizontal(m):
    l = list(m)
    matrix_len = len(l)
    for x in range(0,matrix_len):
        temp = l[x][matrix_len-1]
        l[x][matrix_len-1] = l[x][0]
        l[x][0] = temp
    return l

def mirrorVertical(m):
    l = list(m)
    matrix_len = len(l)
    for x in range(0,matrix_len):
        temp = l[0][x]
        l[0][x] = l[matrix_len-1][x] 
        l[matrix_len-1][x] = temp
    return l


def rotateMatrix(m):
    l = list(m)
    matrix_len = len(l)
    rotated_matrix = []
    for x in range(0,matrix_len):
        rotated_row = []
        for y in range(0, matrix_len):
            rotated_row.append([(matrix_len-1) -y][y])
        rotated_matrix.append(rotated_row)
    return rotated_matrix


# Complete the formingMagicSquare function below.
def formingMagicSquare(s):
    all_matrices = []
    base_matrix = [[8,3,4],[1,5,9],[6,7,2]]
    all_matrices.append(base_matrix)
    print("all matrices after first append",all_matrices)

    base_h_mirror = list(mirrorHorizontal(base_matrix))
    print("horizontal_mirror",base_h_mirror)
    all_matrices.append(base_h_mirror)
    print("all matrices after first h  mirror append",all_matrices)

    base_v_mirror = list(mirrorVertical(base_matrix))
    print("vertical_mirror",base_v_mirror)
    all_matrices.append(base_v_mirror)
    print("all matrices after first v mirror append",all_matrices)


    #Same as vertical mirror of horizontal mirror
    base_v_h_mirror = list(mirrorHorizontal(base_v_mirror))

    all_matrices.append(base_h_mirror)
    print("h_mirror added",all_matrices)

    all_matrices.append(base_v_mirror)
    print("h_mirror added",all_matrices)

    all_matrices.append(base_v_h_mirror)
    print("base_v_h_mirror added",all_matrices)

    print("mirrored matrices= ",all_matrices)

    matrix_len = len(all_matrices)
    for x in range(0,matrix_len):
        all_matrices.append(rotateMatrix(all_matrices[x]))

    print(all_matrices)

formingMagicSquare()

The output , if you run it is something like:

all matrices after first append [[[8, 3, 4], [1, 5, 9], [6, 7, 2]]]

horizontal_mirror [[4, 3, 8], [9, 5, 1], [2, 7, 6]]

all matrices after first h  mirror append
 [
[[4, 3, 8], [9, 5, 1], [2, 7, 6]],
 [[4, 3, 8], [9, 5, 1], [2, 7, 6]]
]
vertical_mirror [[2, 7, 6], [9, 5, 1], [4, 3, 8]]

all matrices after first v mirror append
 [[[2, 7, 6], [9, 5, 1], [4, 3, 8]], 
[[2, 7, 6], [9, 5, 1], [4, 3, 8]],
 [[2, 7, 6], [9, 5, 1], [4, 3, 8]]]

h_mirror added [[[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]]]
h_mirror added [[[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]]]
base_v_h_mirror added [[[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]]]
mirrored matrices=  [[[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]]]

Why is my matrix being populated with the same matrix again and again? I converted the list in the functions i used by slicing it [:]

Upvotes: 0

Views: 58

Answers (1)

Valentino
Valentino

Reputation: 7361

This is also related to mutable and immutable types. You are dealing with lists of lists, which are lists of mutables. So the inner lists are passed by reference, even if you use [:] which makes a shallow copy: a copy of the container, but holding references to the inner object if they are mutables.
That's why, when you change the inner lists, you are changing the same inner lists each time. They are all references to the same lists.

Have a look at the copy docs to more details about shallow copies and deep copies. This will also give you a solution: use a deep copy.

In each function, replace:

l = list(m)

with:

l = copy.deepcopy(m)

Upvotes: 1

Related Questions