2

I try to construct a matrix with a lists of lists in Python3. When I implement the following function,

def myfunction(h, l):
    resultmat = (h+1) * [(l+1) * [0]]
    for i in range(1,h):        
        for j in range(1, l+1):   
            resultmat[i][j] = i + j 
    return resultmat

I get the following result:

myfunction(2,3)
Out[42]: [[0, 2, 3, 4], [0, 2, 3, 4], [0, 2, 3, 4]]

I had expected that the first rows and columns would be filled with zeroes, and that all other elements would be the sum of the row and column index. This is not exactly what I get here, where each row is a copy of the others. Can someone explain me (a) what is going on (b) how I can solve this problem?

DilithiumMatrix
  • 17,795
  • 22
  • 77
  • 119
Laurent Franckx
  • 161
  • 1
  • 6

2 Answers2

3

The problem is the list multiplication. You aren't getting four lists, you're getting one list four times. Use

resultmat = [[0 for i in range(h+1)] for j in range(l+1)]

to build your zero-list instead.

Edit:

Reading the rest of your question, you could probably do the whole thing in a list comprehension

[[i+j if i and j else 0 for i in range(h+1)] for j in range(l+1)]
Patrick Haugh
  • 59,226
  • 13
  • 88
  • 96
1

When you created the initial zero-matrix:

resultmat = (h+1) * [(l+1) * [0]]

This creates a list of lists of zeros. But, the lists of zeros (the rows) are all a reference to the same list. When you change one, it changes all the others:

>>> l = 3*[3*[0]]
>>> l
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> l[0][0] = 1
>>> l
[[1, 0, 0], [1, 0, 0], [1, 0, 0]]
>>>

When I changed the first list to contain a 1, all the lists now contain the 1 because they're all actually the same list.

While Patrick's answer is correct, here is a slightly more readable version of your code, which accomplishes what you want. It creates a matrix for which every cell is the sum of the two indices, and then zeros the first row and the first column.

from pprint import pprint

def create_matrix(height, length):
    matrix = [ [ i + j for j in range(length) ] for i in range(height) ]
    matrix[0] = length*[0]  # zero the first row
    for row in matrix:
        row[0] = 0  # zero the first column
    return matrix

pprint(create_matrix(10, 11))

Output:

[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
 [0, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
 [0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13],
 [0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14],
 [0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
 [0, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
 [0, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17],
 [0, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18],
 [0, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]]
Griff George
  • 895
  • 7
  • 17