Fill a dummy matrix with help of dictionary keys - python

I want to use dictionary keys to get to their respective values and then use these values to reference certain elements in my 2D Array.
I do have a 2d-dummy matrix which I create like this:
self.matrix = [[0] * self.length] * self.length
which creates an N x N matrix depending on the length
I also have a sorted list of nodes that have names (=keys) and I want to map these names to indices (=values) 0..N
self.data = dict(zip(self.nodes, self.index_array))
It all works perfectly fine up until I try to fill my dummy adjacency matrix with "1" for Ni is connected to Nj.
"edges" is a list of tuples: edges = [("u1","v1"),("u1","v2"),...,("ui","uj")]
for row in edges:
self.matrix[self.data[row[0]]][self.data[row[1]]] = 1
Now when I run the method above, I get a matrix that is full of ones when there should only be ones for every connection between node u and node v
I tried modelling this problem in a smaller manner and here it worked perfectly! I don't know what's going on.
a = {"3": 0, "4": 1, "5": 2}
edges = [("3", "5"), ("4", "3"), ("5", "3")]
nodes = ["3", "4", "5"]
index = [0, 1, 2]
data = dict(zip(nodes, index))
matrix = [[0, 0, 0],
[0, 0, 0],
[0, 0, 0]]
for row in edges:
matrix[data[row[0]]][data[row[1]]] = 1
print(a)
print(data)
print(matrix)

This does not create the matrix correctly:
self.matrix = [[0] * self.length] * self.length
Use:
self.matrix = [[0] * self.length for _ in range(self.length)]
The reason is multiplying a list creates multiples of the references in the list, so every row is a reference to the same list in your original code.
Here's an example of the difference:
>>> A = [[0] * 3] * 3
>>> A
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> A [0][0] = 1
>>> A
[[1, 0, 0], [1, 0, 0], [1, 0, 0]]
Note above how all three rows changed. This is due to each row containing a copy of the same list:
>>> A = [[0] * 3 for _ in range(3)]
>>> A
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> A[0][0] = 1
>>> A
[[1, 0, 0], [0, 0, 0], [0, 0, 0]]
Now a new row of three zeroes is created for each row. Changing one element in a row doesn't change all the rows.
Note that [0] * 3 also duplicates the references to the integer zero as well. Being an immutable object this isn't a problem, but if you have a mutable object you don't want three copies. You would use [mutable_obj() for _ in range(3)] to create 3 different objects, so if you edit one the others don't change.

By using the * operator on a list of sublists you're repeating the same references to the sublists, so any change made to a sublist will be reflected on all other items holding the same reference to the sublist.
You can initialize self.matrix with a list comprehension instead:
self.matrix = [[0] * self.length] for _ in range(self.length)]

Related

Syntax Error:Creating An 2d List Filled With Zero

How Could I Initialize An 2D List Filled With Zeroes Without Any Additional Library/Module
here what is my attempt
table = [0 for i in range(amount + 1)[0 for j in range(len(coins))]]
it works in case of 1d list:Vector But Fails In Case Of 2d
Code:
table = [0 for i in range(amount + 1)]
O/P:
[0,0,0,0,0,0,0,0,0,0,0,0]
Code:
table = [0 for i in range(amount + 1)[0 for j in range(len(coins))]]
O/P:
Syntax Error
You are putting the inner comprehension part in the wrong position. Try:
rows, cols = 4, 5
table = [[0 for _ in range(cols)] for _ in range(rows)]
print(table)
# [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
First, _ here is nothing strange; it is just a dummy name, which we don't care. We could name it i for example, and nothing changes.
[... for _ in range(rows)] makes a list with length rows, with the items given by .... Now ... was [0 for _ in range(cols)], i.e., a list of zeros with length cols. Therefore, the result is a list (having length row) of [0, 0, ..., 0].

Updating 2D Array Values in Python - Updating whole column wrong?

I am trying to create a 2D array as such and just update single values at a time, shown here:
M = [[0]*3]*3
M[0][0] = 3
print(M)
which is returning the following:
[[3, 0 , 0], [3, 0, 0], [3, 0, 0]]
Anyone have an idea of what I've done wrong?
What your first line is doing is creating one inner length 3 list, and adding three references of it to your outer list M. You must declare each internal list independently if you want them to be independent lists.
The following is different in that it creates 3 separate instances of inner length 3 lists:
M = [[0]*3 for _ in range(3)]
M[0][0] = 3
print(M)
OUTPUT
[[3, 0, 0], [0, 0, 0], [0, 0, 0]]
The 2D array is at the same address as the first array.
M = [[0,0,0],[0,0,0],[0,0,0]]
M[0][0] = 3
print(M)
Which is returning the following:
[[3, 0, 0], [0, 0, 0], [0, 0, 0]]
FYI: Problem same as this: Why in a 2D array a and *a point to same address?

How to fill up a matrix in Python using for loops

How to add zeroes to the end of a list and fill a matrix with it?
Currently I have
(1,0,1,1,0)
How to fill up a matrix such that it looks like this:
[[0, 0, 0],
[0, 1, 0],
[1, 1, 0]]
In your question, you have clearly added the zeroes to the beginning of the matrix rather than the end but whatever.
To extend a list to one with 9 items with preceeding zeroes:
list_out = [0]*(9-len(list_in)) + list_in
to extend a list to one with 9 items with trailing zeroes just reverse the order:
list_out = list_in + [0]*(9-len(list_in))
We can convert a list with 9 items to a matrix using
matrix = [li[0:3,li[3:6],li[6:9]
so eg.
list_in = [1,2,3]
li = list_in + [0]*(9-len(list_in))
matrix = [li[0:3],li[3:6],li[6:9]]
gives
[[1, 2, 3], [0, 0, 0], [0, 0, 0]]

python two dimensional array with rows and columns

Create a two-dimensional array named A with ROWS rows and COLS columns. ROWS and COLSS are specified by the user at run time. Fill A with randomly-chosen integers from the range [ -10,99 ], then repeatedly perform the following steps until end-of-file(1) input an integer x(2) search for x in A(3) when x is found in A, output the coordinate (row,col) where x is found, otherwise output the message "x not found!"
I need help I am wondering how can we define two-dimensional array named A with ROWS rows and COLS columns. ROWS and COLSS are specified by the user at runtime in python latest version
#--------------------------------------
#Hw 7
#E80
#---------------------------------------
A = [[Rows],[ColSS]] #I really dont know how to defend this part
for i in range (-10,99): #dont worry about this its just the logic not the actual code
x = int(input("Enter a number : "))
if x is found in A
coordinate row and clumn
otherwise output "x is not found"
The idiomatic way to create a 2D array in Python is:
rows,cols = 5,10
A = [[0]*cols for _ in range(rows)]
Explanation:
>>> A = [0] * 5 # Multiplication on a list creates a new list with duplicated entries.
>>> A
[0, 0, 0, 0, 0]
>>> A = [[0] * 5 for _ in range(2)] # Create multiple lists, in a list, using a comprehension.
>>> A
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
>>> A[0][0] = 1
>>> A
[[1, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
Note you do not want to create duplicate lists of lists. It duplicates the list references so you have multiple references to the same list:
>>> A = [[0] * 5] * 2
>>> A
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
>>> A[0][0] = 1
>>> A
[[1, 0, 0, 0, 0], [1, 0, 0, 0, 0]] # both rows changed!

Multiply arrays to make matrix gives unexpected result [duplicate]

This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Closed 8 years ago.
Suppose I have this code:
dim = 3
eye = [[0] * dim] * dim
and it is a list of list, I checked
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
Now, if I do this, I get:
eye[1][2] = 1
eye
[[0, 0, 1], [0, 0, 1], [0, 0, 1]]
However, if I manually put in this expression, the above code works as expected:
eye2=[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
eye2[1][2] = 1
eye2
[[0, 0, 0], [0, 0, 1], [0, 0, 0]]
What is the difference between the two ?
Update: Thanks for all the explanations, suppose I have this code:
a = [0]
type(a)
b = a * 3 # or b = [[0] *3]
So, b holds the 3 references to a. And I expect changing b[0] or b[1] or b[2] will change all 3 elements.
But this code shows the normal behavior, why is that ?
b[1] = 3
b
[0, 3, 0]
Any array entry is as a label of memory address and when you multiple it with a variable actually you create a pointer to 3 palace in your array ! you can figure it out with a list comprehension as below :
Matrix = [[0 for x in xrange(3)] for x in xrange(3)]
dim = 3
eye = [[0] * dim] * dim
its make the copy of same, of if you change at one place it will be reflected to all
dim = 3
eye = [[0] * dim] * dim
print id(eye[0])
print id(eye[1])
print id(eye[2])
Ouput:-
139834251065392
139834251065392
139834251065392
So when you are doing eye = [[0] * dim] * dim it actually refrencing
refrencing three list to same object that is eye.
while in other case
eye2=[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
print id(eye2[1])
print id(eye2[2])
print id(eye2[0])
ouput:-
139863345170480
139863260058256
139863260067240
Here everytime refrence id is diffrent.

Categories