1
def transpose_matrix(matrix):
    n = len(matrix)
    vertical_to_horizontal = [[0]*n]*n
    for i in range(n):
        for j in range(n):
            vertical_to_horizontal[i][j] = matrix[j][i]
    return vertical_to_horizontal


print(transpose_matrix([[1,2],[3,4]]))

The function is supposed to transpose a n*n matrix, but I get [[2, 4], [2, 4]] instead of the correct answer ([1,3],[2,4]).

I know that there are other ways to transpose a matrix, but my problem is to understand why the code above doesn't give the expected result.

Thierry Lathuille
  • 23,663
  • 10
  • 44
  • 50
Kefei
  • 31
  • 3

2 Answers2

2

Your algorithm is correct, the problem lies in the way you create your empty matrix at the beginning, with

vertical_to_horizontal = [[0]*n]*n

The inner [0]*n creates a list [0, 0]

Then, the outer * operator creates a list that references twice this inner list - the very same object.

n = 2
v_to_h = [[0]*n] * n
print(id(v_to_h[0]), id(v_to_h[1]))
#140243497120456 140243497120456

The two [0, 0] lists in your matrix are in fact the same object, as their identical ids shows. So, when we do

v_to_h[0][0] = 5

we update the 0th element of v_to_h[0], but v_to_h[0] and v_to_h[1] are the same object, so we get twice the same list in the matrix:

print(v_to_h)
#[[5, 0], [5, 0]]

If you want to prevent that, you have to create different inner lists, so don't use the * operator.

You can use a list comprehension, as in:

n = 2
v_to_h = [[0]*n for i in range(n)]
print(id(v_to_h[0]), id(v_to_h[1]))
#140243437130184 140243512804488

Here, our two lists are different objects.

So, your code could be:

def transpose_matrix(matrix):
    n = len(matrix)
    vertical_to_horizontal = [[0]*n for i in range(n)]
    for i in range(n):
        for j in range(n):
            vertical_to_horizontal[i][j] = matrix[j][i]
    return vertical_to_horizontal


print(transpose_matrix([[1,2],[3,4]]))
#[[1, 3], [2, 4]]

which does what you expect - though there are, of course, shorter and more efficient ways to transpose a matrix, as already indicated in the comments.

Thierry Lathuille
  • 23,663
  • 10
  • 44
  • 50
  • Nice demonstration! – sascha Jan 11 '18 at 18:28
  • indeed. Just so you can spot this kind of issue, here is a "debugging" version : https://repl.it/repls/JointKlutzyVixen . You can clearly see that both "lines" are being modified at the same time, showing they refer to the same internal array. – Pac0 Jan 11 '18 at 21:44
-1
def transpose_matrix(matrix):
    n = len(matrix)
    vertical_to_horizontal = []
    for i in range(n):
        vertical_to_horizontal.append([i]*n)
        for j in range(n):
            vertical_to_horizontal[i][j] = matrix[j][i]
    return vertical_to_horizontal


print(transpose_matrix([[1,2],[3,4]]))
Hannu
  • 11,685
  • 4
  • 35
  • 51