Home > Software engineering >  How do I reference a specific object based on its attribute, while it is in a loop, in Python?
How do I reference a specific object based on its attribute, while it is in a loop, in Python?

Time:10-21

I have a undirected circular graph of nodes, where the graph is made from a Graph class, and the nodes are made from a Node class. Each node has a few attributes, one of them being the pos attribute. In the Graph class, I have initialized a graph attribute which is a defaultdict. The graph is meant to have nodes of the Node class, with each node pointing to its next and previous nodes based on pos. If the node is 1, its previous node is the last node (let us consider it to have a pos value of 20), and vice versa for the last node. For now I have set each key of graph to have a value of None, but I want to set the value as the neighbors, to indicate edges. Here is what I have done so far:

class Graph:
    def __init__(self) -> None:
        self.graph=defaultdict(Node)
        for i in range(1,21):
            self.graph[Node(i, False, False, False)]=None

    def edge_gen(self):
        for node in self.graph.keys():
            if node.pos==1:
                x=node
                continue
            if node.pos==50:
                self.graph[node.pos].add(x)
                self.graph[x].add(node.pos)
            prev_node=self.graph.keys()[node.pos-1] # Here is where I am lost
            print(prev_node, node)
            self.graph[node.pos].add(prev_node)
            self.graph[prev_node].add(node.pos)
        return self.graph

As indicated by the comment, at that step, I don't understand how to get the object of the neighbor node of the current node based on pos. I first tried to set prev_node as node.pos-1 but I am aware that that won't work. I am putting the keys of graph in a loop, and for each node, I want to add its previous node as a value, and the same for the previous node and the current node. Can someone please help me understand how to get the previous node in this loop to form the edges and therefore create a circular undirected graph? Thanks for reading.

CodePudding user response:

How do I reference a specific object based on its attribute, while it is in a loop, in Python?

If the object in a loop is delivered by an iterator you have in a loop code block access only to this one object. So the answer to your question above is: You can't reference a specific object based on its attribute while looping over an objects delivering iterator.

Having this question answered, my best guess about what you actually want to achieve with the code you provided is as follows:

class Node: 
    def __init__(self, pos, v1, v2, v3):
        self.pos = pos
        self.v1 = v1
        self.v2 = v2
        self.v3 = v3

class Graph:
    def __init__(self, noOfNodes) -> None:
        assert noOfNodes > 2
        self.graph = {}
        self.graph[1] = [ 
            Node(noOfNodes  , False, False, False), 
            Node(    2      , False, False, False), ]
        for i in range(2, noOfNodes):
            self.graph[i] = [ 
            Node( i-1, False, False, False), 
            Node( i 1, False, False, False), ]
        self.graph[noOfNodes] = [ 
            Node(noOfNodes-1, False, False, False), 
            Node(    1      , False, False, False), ]

    def edge_gen(self):
        return self.graph

g = Graph(3)
print(g.edge_gen())

or

class Node: 
    def __init__(self, pos, v1, v2, v3):
        self.pos = pos
        self.v1 = v1
        self.v2 = v2
        self.v3 = v3

class Graph:
    def __init__(self, noOfNodes) -> None:
        assert noOfNodes > 2
        self.noOfNodes = noOfNodes
        self.listOfNodes = [None] # index 0 won't be used  
        for i in range(1, noOfNodes 1):
            self.listOfNodes.append(Node(i , False, False, False))
        self.graph = dict(zip(self.listOfNodes[1:], [None]*noOfNodes))

    def edge_gen(self):
        self.graph[self.listOfNodes[1]] = [ 
            self.listOfNodes[self.noOfNodes], 
            self.listOfNodes[      2       ] ]
        for i in range(2, self.noOfNodes):
            self.graph[self.listOfNodes[i]] = [ 
                self.listOfNodes[i-1], 
                self.listOfNodes[i 1] ]
        self.graph[self.listOfNodes[self.noOfNodes]] = [ 
            self.listOfNodes[self.noOfNodes-1], 
            self.listOfNodes[      1         ] ]
        return self.graph

g = Graph(3)
print(g.graph)
print(g.edge_gen())

Hope this helps to get you off the dead end road of looking for a solution in the wrong direction.

  • Related