This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Closed 3 years ago.
I'm trying to change the value of a certain element in a 2D array.
the 2D array is a num1 by num2 matrix with every element as 0. I'm trying to change the Rth
row Cth column of the matrix to 1
matrix = []
def make_matrix(num1, num2):
row = []
for i in range(num1):
row.append(0)
for i in range(num2):
matrix.append(row)
def change_to_one(R, C):
matrix[R-1][C-1] = 1
make_matrix(3, 2)
change_to_one(2, 1)
print(matrix)
it prints [[1, 0, 0], [1, 0, 0]] instead of [[0, 0, 0], [1, 0, 0]]
This has to do with pointers.
You first define row=[]
When you do this matrix.append(row) num2 times, you are appending the address of row, hence if you change row anytime, it will be broadcasted subsequently.
In other words, changing data in row will change data everywhere you appended row to which in your case is all rows of 2D matrix.
Try this code:
def make_matrix(num1, num2):
for i in range(num2):
row = []
for i in range(num1):
row.append(0)
matrix.append(row)
Here we create a new row everytime and then append it to our matrix, this way changes in any row will not be broadcasted.
There are two problems in your code:
You are using a reference to the original list when you do matrix.append(row[:]). This can be circumvented by just copying the elements of the list as row[:] instead of using row. Otherwise, whatever changes you do to the first row, will also be reflected in all the other rows.
You forgot to return after modifying the matrix. This is not a major problem in your case as the scope of your matrix is global.
matrix = []
def make_matrix(num1, num2):
row = []
for i in range(num1):
row.append(0)
for i in range(num2):
matrix.append(row[:]) # <--- Use row[:] instead of row
def change_to_one(R, C):
matrix[R-1][C-1] = 1
return matrix # <---- return from here
make_matrix(3, 2)
matrix = change_to_one(2, 1) # <---- save the returned result in a variable
print(matrix)
# [[0, 0, 0], [1, 0, 0]]
Related
This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Closed 1 year ago.
I know there are many similar questions like this but I am not sure why my code doesn't work.
Basically, what I am trying to do is to initialize a 2D array to all 0s, get user input (row, column), and set the position to 1.
def printBoard(positions):
for row in positions:
print(row)
def main()
x= int(input())
column = [0] * x
Board= [column] * x
printBoard(Board)
for i in range(x):
row, column = map(int, input().split())
Board[row][column] = 1
printBoard(Board)
main()
But the output is now what I expect.
>>>2
[0, 0]
[0, 0]
>>>1,1
[0, 1]
[0, 1]
As you can see, the whole column is changed. May I ask why?
When you execute
Board= [column] * x
it will result in a list in which all rows (i.e. internal lists) will be the same object (x times the list column), so when you update any element of any of those (same) lists, you will see the result x times, since all the rows (or columns as you call it) are exactly the same, because they are the instances of the same object.
I am currently creating a matrix without using numpy. There's one following case:
If the number of integer input is smaller than the defined dimension of the matrix, 0 is used to fill the empty spaces. For example:
Number inputs = 1,2,3,4 ; Rows = 3 ; Columns = 2
gives (in nested list format): [[1,2],[3,4],[0,0]]
I have the following code for this case:
def mat(*Num,row,col):
Out=[]
for i in range(row):
In = []
for j in range(col):
In.append(0) # Initialize the defined matrix with 0
Out.append(In)
k=0 # Index for number input list
for i in range(len(Out)):
for j in range(i):
Out[i][j]=Num[k] # Update values from integer input list into the matrix
k+=1
return Out
mat(1,2,3,4, row=3, col=2)
However, I got this matrix: [[0, 0], [1, 0], [2, 3]] instead of [[1, 2], [3, 4], [0, 0]]
How should I improve to pass all values into the list in the appropriate positions? Thanks for the help in advance!
Just generate and append new rows
def mat(*num, row, col):
matrix = []
k = 0
n = len(num)
for i in range(row):
new_row = []
for j in range(col):
if k < n:
new_row.append(num[k])
k += 1
else:
new_row.append(0)
matrix.append(new_row)
return matrix
print(mat(1,2,3,4, row=3, col=2))
This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
How do I clone a list so that it doesn't change unexpectedly after assignment?
(24 answers)
Closed 3 years ago.
I am trying to write some code, where in it i need to fill in a matrix and make it the identity matrix and i decided to make this matrix a list of n lists, where each nth list is a row.
I=[]
row=[]
for i in range (0,n):
row.append(0)
for i in range (0,n):
I.append(row)
for k in range (0,3):
I[k][k]=1
I expected this code to put 1's in the matrix's diagonal, where the diagonal are the I[k][k] elements, k=0,1,2.
But in the 3rd for loop, where i am replacing the 0's in the diagonal by 1's, in each step, instead of making I[k][k]=1 it makes
I[0][k]=I[1][k]=I[2][k]=1 and I end up with a matrix with every element equal to 1.
My question is not how to make a identity matrix in python, or any matrix, my question is, why is the 3rd for loop doing that, clearly I[k][k] are diagonal elements, why is it making other non diagonal elements equal to 1?
Great question! In Python, the variables are pointers so what is going on is each element of I is pointing to the same row variable. Thus, when you change an element in one row of I, you are really changing it in all of the rows.
Here is an example:
n = 3
row = []
for i in range(n):
row.append(0)
I = []
for i in range(n):
I.append(row)
Now, let's try to set the first element of the first row to 1, I[0][0] = 1, but in reality this produces [[1, 0, 0], [1, 0, 0], [1, 0, 0]].
Finally, to answer your question, even though you are only setting the diagonal entries of I, it is really setting all of the elements of I because each row is the same in memory. Omari Celestine's answer works because it allocates a new section of memory for each row rather than just one section of memory.
You can nest your for loops when creating the matrix and use the second loop to fill the row and when i is equal to j, then you are in the diagonal of the matrix:
matrix = []
n = 10
for i in range(0, n):
row = []
for j in range(0, n):
if i == j:
row.append(1)
else:
row.append(0)
matrix.append(row)
Suppose that you have two equal-sized lists. First list contains only zeros and ones, and initial value of second list is equal to some fixed number. Other values of second array depends on same-indexed values of first list. Relation between them is that, if value in first list is equal to 0, same-indexed value of second list is equal to preceding one, in all other cases, is equal to some other value. In order to clarify my question, I've written the code below with help of for loop. What is the way to solve this like problem without for loop?
Code
a = np.array([0, 1, 0, 0, 0, 1, 0, 0, 1])
b = np.zeros_like(a)
b[0] = 5
for i in range(1, a.size):
if a[i] == 0:
b[i] = b[i-1]
else:
b[i] = np.random.randint(5)
Here's a vectorized approach -
offset = int(a[0]!=0)
N = (np.count_nonzero(a!=0)) - offset # no. of rand num to be generated
rand_num = np.append(5,np.random.randint(0,5,N))
out = rand_num[(a!=0).cumsum() - offset]
I have no idea how to even begin doing this
It needs to be a for loop to multiply mtrixes
for example
[[1,2],[3,4]] * [[3,4],[5,6]]
[1 , 2] , [3 , 4]
[3 , 4] *[5 , 6]
Need help much appreciated
I know 90% of dont want to code for me so that's ok
It only needs to be two square matrixes
i'm pretty sure the pattern is looking at it in the list thing
a[1][1]*b[1][1]+a[1][2]*b[2][1] a[1][1]b[1][2]+a[1][2]b[2][2]
a[2][1]b[1][1]+a[2][2]b[2][1] a[2][1]b[1][2]+a[2][2]b[2][2]
result = [] # final result
for i in range(len(A)):
row = [] # the new row in new matrix
for j in range(len(B[0])):
product = 0 # the new element in the new row
for v in range(len(A[i])):
product += A[i][v] * B[v][j]
row.append(product) # append sum of product into the new row
result.append(row) # append the new row into the final result
print(result)
Break it down. Before you try to write a function that multiplies matrices, write one that multiplies vectors. If you can do that, multiplying two matrices is just a matter of multiplying row i and column j for every element i,j of the resultant matrix.
If you look at how matrix multiplication works:
[ 1 2 ] x [ 5 6 ] = [ 1*5+2*7 1*6+2*8 ]
[ 3 4 ] [ 7 8 ] [ 3*5+4*7 3*6+4*8 ]
then you can determine a method to calculate this, e.g. if you are multiplying for element i, j of the output matrix, then you need to multiply everything in row i of the LHS matrix by everything in the column j of the RHS matrix, so that is a single for loop (as the number of elements in the row i is equal to column j).
You also need to cover every combination of i and j for the dimensions of the output matrix, which is a for loop for the columns nested inside a for loop for the rows.
The actual code is, of course, an exercise for you to implement.
>>> A=[[1,2],[3,4]]
>>> B=[[3,4],[5,6]]
>>> n=2
>>> ans=[[0]*n for i in range(n)]
>>> ans
[[0, 0], [0, 0]]
>>> for i in range(n):
... for j in range(n):
... ans[i][j]=sum((A[i][v]*B[v][j] for v in range(n)))
...
>>> ans
[[13, 16], [29, 36]]
I think you just need to simplify the formula of matrix multiplication.
We have A*B=C then:
Cij= the value in the ith row and jth column of the answer. For example above we have C12=16 and C11=13.. (note that this is the 0th position in the array so often we start from 0 instead of 1)
Cij= dot_product(row_i_of_A,column_j_of_B)=sum(row_i_of_A(v)*column_j_of_B(v) for v in range(n))
Because we want the whole answer (all of C), we need to work out all possible Cij. This means we need to try all possible pairs ij, so we loop through i in range(n), j in range(n) and do this for each possible pair.
from numpy import *
m1 = array([[1, 2, 3],[4, 5, 6] ])
m2 = array([[7, 8],[9, 10],[11, 12]])
r = array([[0, 0],[0, 0]])
s = 0
for i in range(2):
for j in range(2):
for k in range(3):
s = s + m1[i][k]*m2[k][j]
r[i][j] = s
s = 0
print(r)
I think append function is not working in a two-dimensional array when we are using numpy module, so this is the way I have solved it.
def matmul(matrix1_,matrix2_):
result = [] # final result
for i in range(len(matrix1_)):
row = [] # the new row in new matrix
for j in range(len(matrix2_[0])):
product = 0 # the new element in the new row
for v in range(len(matrix1_[i])):
product += matrix1_[i][v] * matrix2_[v][j]
row.append(product) # append sum of product into the new row
result.append(row) # append the new row into the final result
return result
u and v are constructed for visualization purpose.
from typing import List
A = [[1,0,0],[-1,0,3]]
B = [[7,0,0],[0,0,0],[0,0,1]]
def mult_mat(A:List[List[int]], B:List[List[int]]) -> List[List[int]]:
n = len(A) # Number of rows in matrix A
m = len(B[0]) # Number of columns in matrix B
ret = [[0 for i in range(m)] for j in range(n)]
for row in range(n):
u = A[row]
for col in range(m):
v = [B[i][col] for i in range(len(B))]
# Here you can calculate ret[row][col] directly without v
# But v is constructed for visualization purpose
ret[row][col] = sum([x*y for x,y in zip(u,v)])
return ret
if __name__ == '__main__':
print(mult_mat(A,B))