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)
Related
n = 5
k = 6
matrix = [[j for i in range(n)] for j in range(k)]
for element in matrix[3]:
print(element)
element = 100
print(matrix)
I expect to see one row in my matrix to be all 100 at the end, but the values are all still initial values, why is this happening?
When you run:
for element in matrix[3]:
element = 100
all you're doing is changing the element inside the for loop. When another round of the for loop starts, element is changed back to what it should be, i.e.: the next element in the matrix. You can think of element as a temporary variable that changes every run of the loop.
More importantly, 'element' is now separate from the matrix. Changing 'element' will not change the matrix. You need to directly call on the matrix element you want to change and assign it whatever value you want to set it to. The proper way to do this would be to do:
for i in range(len(matrix[3])):
matrix[3][i] = 100
Check the code below for what the right code should look like.
n = 5
k = 6
matrix = [[j for i in range(n)] for j in range(k)]
for i in range(len(matrix[3])):
matrix[3][i] = 100
print(matrix)
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.
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]]
I'm trying to create a bidimensional array using list comprehension.
a = [[0 for y in range(1, 10)] for x in range(1, 10)]
This should create a 9x9 'matrix' whose first item is a[1][1], and last is a[9][9]
However this is not happening, and when I try to print the last element:
print(a[9][9])
I get an out of range error.
What am I doing wrong?
You do have a 9x9 matrix (or list of lists), but since indices are zero based, you can only index from 0 to 8 along both axes.
The start value 1 in the range function does not influence the start value of your indexing; it will always be zero.
I am stuck in question relating to the two dimension list, the questions are Write a program that constructs a two dimensional list containing 5 lists each containing 5 elements. The value of the ith element in the jth list should be j×5+i using the code.
Adapt the program from the previous question so that it asks the user for two dimensions, then constructs a two dimensional list with the specified dimensions with the values as described in the previous questions.
As I am a new to programming please can you help me.
#create a variable called a of type list
a = []
for I in range(5):
#append an empty list to a
a.append([])
for j in range (5):
#append 0 to the ith list of a
a[I].append(0)
#print a
print(a)
This should do the work
x = input('Type a value for the number of lines: ')
y = input('Type a value for the number of columns: ')
#create a variable called a of type list
a = []
for i in range(x):
#append an empty list to a
a.append([])
for j in range (y):
#append 0 to the ith list of a
a[i].append(j*5+i)
#print a
print(a)
I think list comprehension wins here:
[[j*5+i for j in range(5)] for i in range(5)]