I have created a matrix using list within a list, and want to replace an element at a specific index according to a given data.
However, when I change an element in the 0th list, it changes the elements of all other lists with the same index
Could someone please tell me what's going on and how to resolve this?
def directed(raw_list, weighted):
"""for directed graph"""
#for weighted
adj_matrix = None
if weighted is True:
#create an empty matrix n*n
v_num = int(raw_list[0][1])
row = [None for item in range(v_num)]
adj_matrix = [row for item in range(v_num)]
#then use a while loop to input values
i = 1
while i < len(raw_list):
source = int(raw_list[i][0])
destination = int(raw_list[i][1])
weight = int(raw_list[i][2])
adj_matrix[source][destination] = weight
i = 1
#for unweighted
else:
#create an empty matrix with 0s, n*n
v_num = int(raw_list[0][1])
row = [0 for item in range(v_num)]
adj_matrix = [row for item in range(v_num)]
#then while loop
i = 1
#print(raw_list)
while i < len(raw_list):
source = int(raw_list[i][0])
print(source)
destination = int(raw_list[i][1])
#print(destination)
#in case a loop
if source == destination:
adj_matrix[source][destination] = 2
#otherwise
else:
adj_matrix[source][destination] = 1
i = 1
#return the adj_matrix
return adj_matrix
def undirected(raw_list, weighted):
"""for undirected graph"""
#for weighted
adj_matrix = None
if weighted is True:
#create an empty matrix n*n
v_num = int(raw_list[0][1])
row = [None for item in range(v_num)]
adj_matrix = [row for item in range(v_num)]
#then use a while loop to input values
i = 1
while i < len(raw_list):
source = int(raw_list[i][0])
destination = int(raw_list[i][1])
weight = int(raw_list[i][2])
adj_matrix[source][destination] = weight
adj_matrix[destination][source] = weight
i = 1
#for unweighted
else:
#create an empty matrix with 0s, n*n
v_num = int(raw_list[0][1])
row = [0 for item in range(v_num)]
adj_matrix = [row for item in range(v_num)]
#then while loop
i = 1
while i < len(raw_list):
source = int(raw_list[i][0])
destination = int(raw_list[i][1])
#in case a loop
if source == destination:
adj_matrix[source][destination] = 2
#otherwise
else:
adj_matrix[source][destination] = 1
adj_matrix[destination][source] = 1
i = 1
#return the adj_matrix
return adj_matrix
def adjacency_matrix (graph_str):
"""creates adjacency matrix from a given string-form graph"""
#split the string into lines
raw_string = graph_str.splitlines()
#then into lists
raw_list = [item.split() for item in raw_string]
#check directed or undirected
direct = 'D' in raw_list[0]
#check weighted or not
weighted = 'W' in raw_list[0]
#send off to the respective helper functions
adj_matrix = None
if direct is True:
adj_matrix = directed(raw_list, weighted)
else:
adj_matrix = undirected(raw_list, weighted)
#return the finished adjacency matrix
return adj_matrix
#Tests
graph_string = """\
D 3
0 1
1 0
0 2
"""
print(adjacency_matrix(graph_string))
#[[0, 1, 1], [1, 0, 0], [0, 0, 0]]
CodePudding user response:
In this code:
row = [None for item in range(v_num)]
adj_matrix = [row for item in range(v_num)]
you're populating adj_matrix
with v_num
identical references to row
(a single list).
What you want to do instead is create a new list for each element of adj_matrix
:
adj_matrix = [[None] * v_num for _ in range(v_num)]
Note that there's no harm in doing [None] * v_num
to initialize each row as a list of identical references to None
, because None
is an immutable singleton; you only need to be careful about duplicated references with mutable objects (like lists), where mutating one reference will impact the others.