Reputation: 129
I'm trying to tranpose a matrix in Python 3.x without using numpy. For some reason, I'm having problems with the assignment of new_matrix[col_num][row_num]
. For example, if I create a new instance of Matrix like test = Matrix([[1,2,3,],[4,5,6],[7,8,9]])
, the first time it goes through the inner for loop, new_matrix becomes [[1,None,None],[1,None,None],[1,None,None]]
instead of [[1,None,None],[None,None,None],[None,None,None]]
. I can't figure out why this is happening and why it's assigning a value to ALL the first elements of lists.
class Matrix:
def __init__(self, matrix):
self.matrix = matrix
def transpose(self):
new_matrix = [[None] * len(self.matrix[0])] * len(self.matrix)
row_num = 0
for row_num in range(len(self.matrix)):
for col_num in range(len(self.matrix[0])):
print(new_matrix[col_num][row_num])
print(new_matrix)
#assignment assigning more than one variable
new_matrix[col_num][row_num] = self.matrix[row_num][col_num]
print(new_matrix[col_num][row_num])
print(new_matrix)
col_num = 0
return new_matrix
Upvotes: 2
Views: 1884
Reputation: 18628
new_matrix = [[None] * len(self.matrix[0])] * len(self.matrix)
must be replaced by
new_matrix = [[None for j in self.matrix[0]] for i in self.matrix]
This way, all the None will be "differents".
but the shorter way is to directly build the result with extension lists :
MT= [[M[j][i] for j in range(len(M))] for i in range(len(M[0]))]
Upvotes: 2
Reputation: 476534
That's because you construct the newmatrix
with:
new_matrix = [[None] * len(self.matrix[0])] * len(self.matrix)
If you do:
<array-expr> * number
you do not copy that list, you copy the reference. So that means that when you manipulate newmatrix[0]
you also manipulate newmatrix[1]
, etc.
You should solve it with list-comprehension:
new_matrix = [[None] * len(self.matrix[0]) for _ in range(len(self.matrix))]
Since here you actually construct a new list for each row.
So the algorithm should look:
class Matrix:
def __init__(self, matrix):
self.matrix = matrix
def transpose(self):
new_matrix = [[None] * len(self.matrix[0]) for _ in range(len(self.matrix))]
row_num = 0
for row_num in range(len(self.matrix)):
for col_num in range(len(self.matrix[0])):
print(new_matrix[col_num][row_num])
print(new_matrix)
#assignment assigning more than one variable
new_matrix[col_num][row_num] = self.matrix[row_num][col_num]
print(new_matrix[col_num][row_num])
print(new_matrix)
col_num = 0
return new_matrix
Upvotes: 2
Reputation: 273376
Here's a hint:
In [9]: arr = [[None] * 2] * 3
In [10]: arr
Out[10]: [[None, None], [None, None], [None, None]]
In [11]: arr[1][1] = 2
In [12]: arr
Out[12]: [[None, 2], [None, 2], [None, 2]]
Do you see the problem?
The list replication (*
operator) repeats the same nested list object within the containing list. Instead, you should be creating a new list every time.
Upvotes: 1