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.
Related
This question already has answers here:
Strange result when removing item from a list while iterating over it
(8 answers)
Closed last year.
This is the code I have used and it is not removing last zero it is skipping
x = [1,2,3,0,0,0]
for I in x:
if I==0:
x.remove(I)
print(x)
output:
[1, 2, 3, 0]
so from the output the last zero is not removing why
Why don't you use this simple list comprehension.
x = [1,2,3,0,0,0]
y=[i for i in x if i != 0]
print(y)
You'll get a new list (y) with the 0 removed, while the x is preserved in it's original state.
[1, 2, 3]
Process finished with exit code 0
For more study on list.remove(), check this
List.remove() does not remove all occurrances
As per documentation, list.remove removes first element whose value matches given number.
So, when first '0' at index 3 is removed, the new list is [1,2,3,0,0] with the list iteration index at 4. The following 0 (which was at index 4 in original list) moves back one place and is getting skipped. This can be seen with following code:
x = [0,0,0,0,0,0]
for id, i in enumerate(x):
print(id, i)
if i == 0:
print(x, i)
x.remove(i)
print(x)
In this, every second element is missed, and final x is [0, 0, 0]
As for what is correct way to do this, list comprehension is a good way, as answered by Anand: x = [i for i in x if i!=0]
This question already has answers here:
Why does range(start, end) not include end? [duplicate]
(11 answers)
Closed 2 years ago.
I'm sorry for the very basic question, this is a concept I can't quite grasp.
It is my understanding that the first element in a Python list has index [0]. This means that len(x)-1 should be the last element in my list x.
So, if I write a loop with:
for i in range(0, len(x)-1):
#do stuff here
This should mean that I want I to go from the first element of my list to the last one.
However, I always find written:
for i in range(0, len(x)):
#do stuff here
Why is that?
Which one is correct?
range(0,x) will loop up to the value of x, so < x as opposed to <= x. For example, range(0, 3) will loop over the indices 0, 1, 2.
Which means the second one is correct, as if x = [4, 5, 6, 7] (len 4) - the maximum index is 3 so you'd want to loop over the indices 0, 1, 2, 3.
range(x, y) means to start with x and iterate till y-1 so when you use for i in range(0, len(x)-1):, it will iterate from 0 to len(x) - 2.
For example if, len(x) = 3, the statement for i in range(0, len(x)-1): will iterate from 0 to 1 so that's why we use for i in range(0, len(x)): to iterate over all the elements in the list.
This question already has answers here:
Subtracting 2 lists in Python
(16 answers)
Closed 2 years ago.
So I want to be able to subtract a list to another list.
For example, if I had two lists:
x = [0,8,10]
y = [1,7,9]
I would like to be able to basically subtract y[i] - x[i] using a FOR LOOP.
So ultimately, inside the loop, it would go 1-0, 7-8, 9-10, and so on if the list is longer.
Additionally, would there be any way to check if all or only one of the differences are equal to each other?
Thank you.
Try this :
import operator
x = [0,8,10]
y = [1,7,9]
ans = list(map(operator.sub, y, x))
print(ans)
Output :
[1, -1, -1]
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]]
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)