class Node:
def __init__(self, name):
self.connections = set()
self.name = name
self.total_cost = -1
self.last_connection = None
self.visited = False
def __str__(self):
return f"Name: {self.name}, total cost: {self.total_cost}, connections: {[(node.name, cost) for node, cost in self.connections]}"
__repr__ = __str__
def parse_graph(lines):
graph = {}
for line in lines:
if line.startswith("node "):
name = line[5:]
# Get the node if it already exists, otherwise create a new node
node = graph.setdefault(name, Node(name))
elif line.startswith(("\t", " "*4)): # some editors might replace \t with 4 spaces, careful!
name2, cost = line.strip().split(",")
# Get the other node if it already exists, otherwise create a new node
node2 = graph.setdefault(name2, Node(name2))
# add connectionsconnection manually, no need to iterate over all existing connections
# reverse connection added in definition of node2
node.connections.add((node2, int(cost))) # int can deal with whitespace
else:
raise ValueError(f"Cannot parse line: {line}")
return graph
The crucial part here is adding a node when you see it the first time (even just as a target of a connection) and getting the same node back again when it already exists. For this I used dict.setdefault, which is functionally equivalent to:
if name not in graph:
graph[name] = Node(name)
node = graph[name]
Currently there is no sanity check that all nodes that are referenced as targets of connections are actually defined, you might want to add that.