Below is my code.
check = [[0] * 4] * 2
check[0][1] = 1
print(check)
check2 = [[0, 0, 0, 0], [0, 0, 0,0]]
check2[0][1] = 1
print(check2)
result:
[[0, 1, 0, 0], [0, 1, 0, 0]]
[[0, 1, 0, 0], [0, 0, 0, 0]]
I expect check and check2 get same result but it is different.
why check[0][1] and check[1][1] are changed?? not only check[0][0]
check is a shallow copy
check = [[0] * 4] * 2 - Creates only one list [0,0,0,0] and rows 1 and 2 refer to this list.
So changing the elements of one row reflects changes in every other row.
To avoid such a scenario you can use a for-loop to create the list like this
check = [[0 for _ in range(4)] for _ in range(2)]
Now, this will be a deep copy and not shallow copy.
check2 is a deep copy.
check2 = [[0, 0, 0, 0], [0, 0, 0,0]] - Creates two separate lists [0,0,0,0]. Row 1 and Row 2 refers to different copies of [0,0,0,0]
So changing the elements of one row will not reflect any changes in the other row.
Please read this SO answer to fully understand the concepts. https://stackoverflow.com/a/37830340
Related
I'm trying to create an identity matrix that accepts input and returns an identity matrix(list or lists) of size by size, with only 1's and 0's without using numpy.
So if the user inputs: >>>matrix(4), the output should be: [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]
So far I've setup my list comprehension like this:matrix = [[0 for _ in range(3)] for _ in range(3)]
Any suggestions on how to setup my comprehension would be appreciated.
Can cast a bool to an int to quickly get either a 0 or 1
def matrix(N):
return [[int(col == row) for col in range(N)] for row in range(N)]
I have a BxCxd tensor of coordinates and want to repeat each row in the following way:
[[[1,0,0],[0,1,0],[0,0,1]]] -> [[[1,0,0],[1,0,0],[0,1,0],[0,1,0],[0,0,1],[0,0,1]]]
In the above example each row is repeated 2 times. What's especially important is the ordering. Each row in the first tensor should appear k times in the second one before the next row appears.
I tried the following code:
print(x.size())
params = x.repeat_interleave(self.k, dim=-1).permute(0,2,1)
In the above snippet, x is of size 32x128x4 before repeat_interleave. With self.k = 64 I would expect the result to be a 32x8192x4 tensor, however the result I am getting is 32x256x128 which does not make sense to me. What am I missing here?
I think you want:
t.repeat_interleave(2, dim=1)
Output:
ensor([[[1, 0, 0],
[1, 0, 0],
[0, 1, 0],
[0, 1, 0],
[0, 0, 1],
[0, 0, 1]]])
Expected Output:
indenitiy_matrix(3)
[[1, 0, 0], [0, 1, 0], [0, 0, 1]]
Actual Output with Error:
indenitiy_matrix(3)
[[1, 1, 1], [1, 1, 1], [1, 1, 1]]
def identity_matrix(n):
list_template = [[]]
list_n = list_template*n
for sub_l in list_n:
sub_l.append(0)
for val in range(n):
# I have the feeling that the problem lies somewhere around here.
list_n[val][val]=1
return(list_n)
list_template*n does not create n copies, instead but all those n copies reference to only one copy. For example see this
a = [[0,0,0]]*2
# Now, lets change first element of the first sublist in `a`.
a[0][0] = 1
print (a)
# but since both the 2 sublists refer to same, both of them will be changed.
Output:
[[1, 0, 0], [1, 0, 0]]
Fix for your code
def identity_matrix(n):
list_n = [[0]*n for i in range(n)]
for val in range(n):
list_n[val][val]=1
return list_n
print (identity_matrix(5))
Output:
[[1, 0, 0, 0, 0],
[0, 1, 0, 0, 0],
[0, 0, 1, 0, 0],
[0, 0, 0, 1, 0],
[0, 0, 0, 0, 1]]
No, the problem lies here:
list_template = [[]]
list_n = list_template*n
After this, try doing:
list_n[0].append(1) # let's change the first element
The result:
[[1], [1], [1], [1], [1]]
is probably not what you expect.
Briefly, the problem is that after its construction, your list consists of multiple references to same list. A detailed explanation is at the link given by #saint-jaeger : List of lists changes reflected across sublists unexpectedly
Finally, the numpy library is your friend for creating identity matrices and other N-dimensional arrays.
This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Closed 2 years ago.
I'm trying to make the input maze of Astar algorithm(alogorithm to find the shortest path between start and destination and there can be some blockages within the maze,
which takes input a maze representing blockages only, as shown below).
From the GUI using the Click1 command in each button,
I intend to get an output like this(where I inserted a blockage at [3][2]).
1 represents blockage which is to avoided to find the path from start to end.
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 1, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
but I get a output as following,I can't understand why it's blocking the same column of each and every row
[[0, 1, 0, 0, 0], [0, 1, 0, 0, 0], [0, 1, 0, 0, 0], [0, 1, 0, 0, 0], [0, 1, 0, 0, 0]]
I created the maze in the init(): of class App() using this:
def __init__(self, master,dimension,indexes):
self.maze=[[0]*self.dimension]*self.dimension
this entire thing is within a class App():
for creating the grid of buttons, and storing their reference
self.gid = []
for i in range(self.dimension):
row = []
Grid.rowconfigure(self.frame1, i + 1, weight=3)
for j in range(self.dimension):
Grid.columnconfigure(self.frame1, j + 1, weight=3)
btn=Button(self.frame1,command=lambda i=i, j=j: self.Click1(i, j))
btn.grid(sticky=N+S+E+W,padx=2,pady=2,ipadx=1,ipady=1)
row.append(btn)
row[-1].grid(row=i + 1, column=j+1)
self.gid.append(row)
the Click1 method/Command that also within this class:
def Click1(self, i, j):
self.indxes.append((i,j))
if len(self.indxes)==1:
self.gid[i][j]["bg"]="blue" #indicates start
elif len(self.indxes)==2:
self.gid[i][j]["bg"]="green" #indicates destinations
else:
self.gid[i][j]["bg"] = "black"
self.maze[i][j] = 1 #how I insert blockage within the maze
Try this in your init:
def __init__(self, master,dimension,indexes):
self.maze = [[0] * self.dimension] for _ in range(self.dimension)]
The latter * self.dimension call was assigning the same reference to all your inner lists (dimension number of times) - meaning when one is changed all will change.
This creates a unique list for each sublist
num_row = 3
num_col = [2, 4, 8]
# columns, row
list_2d = [[0 for i in range(num_row)] for j in num_col]
#list_2d = [[0 for i in range(num_row)] for j in num_col[:]] # SyntaxError: invalid syntax
#list_2d = [[0 for i in range(num_row)] for num_col[:]] #SyntaxError: invalid syntax
#list_2d = [[0 for i in range(num_row)] for j in num_col[j]] #IndexError: list index out of range
print('\nlist_2d:')
for i in list_2d:
print(i)
print('\nnum_col:')
for j in num_col[:]:
print(j)
My goal is to declare/initialize a list of list where the number of row elements is provided by an array (i.e., the first element of the array gives the number of columns in the first row, the second element of the array gives the number of columns in the second row, etc.). For the life of me, I cannot figure out how to accomplish this.
What I get:
list_2d:
[0, 0, 0]
[0, 0, 0]
[0, 0, 0]
num_col:
2
4
8
What I want:
[0, 0]
[0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0]
[[0 for i in range(j)] for j in num_col]
num_row will always be three, you want to use j instead
Another way would be to use *. Here's an example
>>> [0]*10
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
Applying the same, you could also do this as follows:
num_col = [2,4,8]
result = [[0]*j for j in num_col]