0

I am trying to write simple function that will return sum of two matrices (nested lists). I do not understand why the code below does not work as expected. Note that all printed steps are fine, but the result at the end is not.

Code:

matrix_a = [[1, 2, 4], [0, 1, 3], [2, 2, 8]]
matrix_b = [[0, 3, 1], [5, 4, 2], [8, 2, 6]]

rows = len(matrix_a)
columns = len(matrix_a[0])
result = [[0] * columns] * rows
for x in range(rows):
 for y in range(columns):
   result[x][y] = matrix_a[x][y] + matrix_b[x][y]
   print(f'[{x}][{y}]: {matrix_a[x][y]} + {matrix_b[x][y]} = {result[x][y]}')
print(result)

Output:

[0][0]: 1 + 0 = 1
[0][1]: 2 + 3 = 5
[0][2]: 4 + 1 = 5
[1][0]: 0 + 5 = 5
[1][1]: 1 + 4 = 5
[1][2]: 3 + 2 = 5
[2][0]: 2 + 8 = 10
[2][1]: 2 + 2 = 4
[2][2]: 8 + 6 = 14
[[10, 4, 14], [10, 4, 14], [10, 4, 14]]

Could you tell my how to fix it and, what is more important for me, why last row is copied three times?

docp
  • 307
  • 1
  • 9

3 Answers3

2

When you do [[0] * columns] * rows you're creating a list of 3 references to the same list.

It is equivalent to the following code:

a = [0, 0, 0]      # a = [0] * columns
result = [a, a, a] # result = [a] * rows

Hence when you do result[0], result[1] and result[2] you're actually referencing the same underlying memory as a. Since they all reference the same object, when you do the last three lines

[2][0]: 2 + 8 = 10
[2][1]: 2 + 2 = 4
[2][2]: 8 + 6 = 14

You're actually modifying the same underlying entity, a (in our case).

If you want to allocate the result array programmatically, then you'll have to do

result = [[0] * columns for _ in range(rows)]

Addendum: Now you may ask why does [0] * columns not show the same behaviour, ie. Why isn't your entire results array the value 14. This is to do with how Python manages the underlying memory, and it has a lot to do with if the data type is trivially copyable or not (such as primitives) and if the data type is immutable or not (such as tuples vs lists).

Perse95
  • 121
  • 1
  • 5
1

Problem is the way you are initializing your result,

[[0] * columns] * rows] # results in reference being same,

what's happening above is you are creating a single array [0, 0, 0] and referencing it 3 times.

change it to

[[0] * columns] for _ in range(rows)]. # separate lists would be created.

Vaibhav Mishra
  • 11,384
  • 12
  • 45
  • 58
-1
matrix_a = [[1, 2, 4], [0, 1, 3], [2, 2, 8]]
    matrix_b = [[0, 3, 1], [5, 4, 2], [8, 2, 6]]
    
    result = []
    for row in range(len(matrix_a)):
        x = []
        for col in range(len(matrix_a[row])):
            summed_row_array = matrix_a[row][col] + matrix_b[row][col]
            x.append(summed_row_array)
    
        result.append(x)
    
    
    print(result)
Dharman
  • 30,962
  • 25
  • 85
  • 135
Marcin
  • 302
  • 3
  • 11