Home > Back-end >  Changing a value in a list of list changes all other elements of other list with the same index
Changing a value in a list of list changes all other elements of other list with the same index

Time:03-15

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.

  • Related