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.