Nested for loop to transpose matrix - python

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.

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.

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]]))

Related

How to get triplets from an array?

I have [1,2,3] and I wish to get [(1,1,1), (1,4,9), (1, 8, 27)]. What is the easiest way to achieve this?
I'd probably do this with a list comprehension, an inner loop iterating over your array/list, i. e. [1,2,3] and an outer loop iterating over the powers , i. e. zero, one and two (EDIT: To achieve the output you specified in your question one would need [0,2,3] as powers list):
elements = [1,2,3]
powers = [0,1,2]
[[e**i for e in elements] for i in powers]
The output of this is
[[1, 1, 1], [1, 2, 3], [1, 4, 9]]
If you want a numpy array you can convert it with np.array() and if you want a list of tuples as you have it written in your question convert it with tuple(), i. e.
import numpy as np
elements = [1,2,3]
powers = [0,1,2]
# numpy array
np.array([[e**i for e in elements] for i in powers])
# list of tuples
[tuple([e**i for e in elements]) for i in powers]
I'd do it this way, check it out:
def get_cuadrado_cubo(lista):
resp = []
for i in range (4):
if i == 1:
continue
resp.append((lista [0] ** i, lista [1] ** i, lista [2] ** i) )
return resp

how to fill matrix using range without numpy?

I created a matrix of zeros using lists, and I want to fill it based on matrix size, but I want the numbers to come sequentially.
I tried the following
matrix = []
for i in range(3):
a =[]
for j in range(3):
a.append(i+j)
matrix.append(a)
I get this:
[[0, 1, 2], [1, 2, 3], [2, 3, 4]]
but the expected is:
[[0, 1, 2], [3, 4, 5], [6, 7, 8]]
thanks
Have your outer range loop with a step to provide the base value for each level. In this case, just change:
for i in range(3):
to:
for i in range(0, 9, 3):
It might be slightly more readable to phrase it in terms of a named variable like dim (for "dimension"):
dim = 3
for i in range(0, dim ** 2, dim):
a = []
for j in range(dim):
a.append(i+j)
matrix.append(a)
Tagging on to #ShadowRanger's answer, rather than appending you can use a list comprehension if you would like.
dim = 3
matrix = [list(range(i, i+dim)) for i in range(0, dim**2, dim)]
You could multiply i by 3 like so:
matrix = []
for i in range(3):
a =[]
for j in range(3):
a.append(3*i + j) <-----
matrix.append(a)

In what order is this Python list comprehension executed? [duplicate]

This question already has answers here:
Nested list comprehensions
(3 answers)
Closed 6 years ago.
I am a bit confused by this list comprehension:
l = [[i * j for j in range(3, 5)] for i in range(3)]
In what order is it executed?
This is a pretty vanilla list comprehension of the form:
[expression for var in iterable]
In this case, expression just happens to be another list comprehension. So, the inner comprehension will evaluate once for each item yielded by the outer iterable.
It might feel a little more clear if we broke the inner comprehension out into a function:
def inner(i):
return [i * j for j in range(3, 5)]
l = [inner(i) for i in range(3)]
Now we see more clearly (hopefully anyway) that the outer comprehension causes the inner comprehension to execute once for each "i" in range(3).
Imagine it being executed from the outside in.
[X for i in range(3)]
In this case, the X is itself another list comprehension:
[i*j for j in range(3,5)]
within which i is bound to a single value.
So it expands to [[0*3,0*4],[1*3,1*4],[2*3,2*4]], or [[0,0],[3,4],[6,8]],
In the following:
l = [[i * j for j in range(3, 5)] for i in range(3)]
i takes on the values 0, 1, and 2. For each value of i, the nested list comprehension is evaluated and the result saved to the top-level list:
[i * j for j in range(3, 5)]
Here, j takes on the values 3 and 4. For each value, the product of j with the current value of i is saved.
For the first value of i, i.e. 0, this is 0 times the j values, so you get [0, 0].
For the second value of i, i.e. 1, this is 1 times the j values, so you get [3, 4].
For the third value of i, i.e. 2, this is 2 times the j values, so you get [6, 8].
The final result is the list composed of these three sub-lists, so you get:
[[0, 0], [3, 4], [6, 8]]
l = [[i * j for j in range(3, 5)] for i in range(3)]
can be imagined as:
(1) l = [[i * j for j in range(3, 5)] with i = 0] => [[0*3, 0*4]]= [[0,0]]
+(2) l = [[i * j for j in range(3, 5)] with i = 1] =>[[0,0], [3,4]]
+(3) l = [[i * j for j in range(3, 5)] with i = 2] =>[[0,0], [3,4], [6,8]]

Transposing a matrix using loops

Given the matrix
matrix = [[2, None],
[2, None]]
I need to compute the transpose of this. I did the following:
def transpose(matrix):
# Makes a copy of the matrix
result = matrix
# Computes tranpose
for i in range(2):
for j in range(2):
result[j][i] = matrix[i][j]
return result
But this gives me the false result:
[[2, None],
[None, None]]
while it should be
[[2, 2],
[None, None]]
Can someone tell me where I went wrong with my code?
You a referencing to the same matrix, try initializing a new one:
def transpose(matrix):
# Makes a copy of the matrix
result = [[None]* len(x) for x in matrix]
# Computes tranpose
for i in range(2):
for j in range(2):
result[i][j] = matrix[j][i]
return result
You can also do it for a generic matrix using list comprehesion
def transpose(matrix):
return [[matrix[i][j] for i in range(len(matrix[j]))] for j in range(len(matrix))]
The problem is that the variable result refers to matrix, that is, you do not make a copy, so in the for-loop you actually also change matrix. You can solve this by making a copy of matrix in result with list:
result = [list(x) for x in matrix]
See the question: How to clone or copy a list?
Note that an easier way is to use NumPy:
import numpy as np
matrix = np.matrix([[2, None],[2, None]])
then use matrix.T to get the transpose:
matrix([[2, 2],
[None, None]], dtype=object)
# We can use the below method also:
matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
mat_trans = []
trans = []
trans1 = []
trans2 = []
trans3 = []
for row in matrix:
for i in range(4):
if i == 0:
trans.append(row[i])
if i == 1:
trans1.append(row[i])
if i == 2:
trans2.append(row[i])
if i == 3:
trans3.append(row[i])
mat_trans.append(trans)
mat_trans.append(trans1)
mat_trans.append(trans2)
mat_trans.append(trans3)
trans = []
print(mat_trans)
Assuming that the matrix is rectangular (i.e. same list size in all one-D arrays), one can simply write a transpose as the following.
def transpose(matrix):
num_rows = len(matrix)
num_cols = len(matrix[0])
result = []
for j in range(num_cols):
rowresult = []
for i in range(num_rows):
rowresult.append(matrix[i][j])
result.append(rowresult)
return result
Note: This is not the most efficient implementation.

Matrix Addition in Python - list

I'm trying to write Matrix Addition function using Python.
Here is the code I've been trying, but it gives me a list index error and I cannot figure out why.
def matrixADD(A,B):
Z = []
#TODO
for i in range(0,len(A)):
for column in range(0, len(A)):
result = A[i][column] + B[i][column]
Z[i][column] = (result)
return Z
using the following lists:
A = [[2,4], [7,0], [6,3]]
B = [[3,1], [-1,8], [-3, 3]]
So in theory, A[0][0] + B[0][0] would equal 5, and I would want to add that value to position Z[0][0].
However I keep receiving the error: IndexError: list index out of range
>>> A = [[2,4], [7,0], [6,3]]
>>> B = [[3,1], [-1,8], [-3, 3]]
>>> Z = [map(sum, zip(*t)) for t in zip(A, B)]
>>> Z
[[5, 5], [6, 8], [3, 6]]
As for how you could fix your current code:
Z = []
for i in range(len(A)):
row = []
for j in range(len(A[i])):
row.append(A[i][j] + B[i][j])
Z.append(row)
The important parts here being that you cannot just assign to Z[i][j] unless that row/column already exists, so you need to construct each inner list separately and append them to Z. Also the inner loop needs to end at the length of a row, so I changed range(len(A)) to range(len(A[i])).
len(A) = 3 but you matrix have dimension 3x2 so when you try to access A[2][2] (because column is between 0 and len(A)) you are out of bounds.
For column you are using range 0 to len(A) (which is 3). A[i][2] will be out of range, because A[i]'s length is only 2.
Try using column range to end a len(A[i]) instead of len(A):
def matrixADD(A,B):
Z = []
#TODO
for i in range(0,len(A)):
for column in range(0, len(A[i])):
result = A[i][column] + B[i][column]
Z[i][j] = (result)
return Z

Categories

Resources