Python – How to convert a List into an Adjacency List for graphs structure

Question:

My problem is that I can’t convert a graph constructed through a list into a graph constructed as a dictionary, which must act as an adjacency list.

I have already constructed a random generated graph by randomly adding to each edge: start node (string), end node (string), weight (int).
But now I would need to convert it to a graph like this (a dictionary) that represent an adjacency list:

example_graph = {
        'A': {'B': 2, 'C': 3},
        'B': {'A': 2, 'C': 1, 'D': 1, 'E': 4},
        'C': {'A': 3, 'B': 1, 'F': 5},
        'D': {'B': 1, 'E': 1},
        'E': {'B': 4, 'D': 1, 'F': 1},
        'F': {'C': 5, 'E': 1, 'G': 1},
        'G': {'F': 1},
    }

These graphs must be the same, that’s why i need to convert the first one.
So what I did then is to put those three initial values (start node, end node, weight) into a list called graphConvert like this:

        while i < graph.numberOfNodes():
        graphConvert.insert(i, list(zip(graph.edges[i].node1.printSingleNode(), graph.edges[i].node2.printSingleNode(), [graph.edges[i].weight])))

        deleteIntegers.append(graph.edges[i].weight)
        i += 1
    deleteIntegers = list(set(deleteIntegers))

That’s an example of the result: [[(‘C’, ‘B’, 4)], [(‘A’, ‘D’, 2)], [(‘D’, ‘C’, 3)], [(‘A’, ‘C’, 4)]]

Then i added this code to convert the list into a dictionary:

adj_list = {}
    for edge_list in graphConvert:
        for edge in edge_list:
            for vertex in edge:
                adj_list.setdefault(vertex, set()).update((set(edge) - {vertex}))

    for i in range(deleteIntegers.__len__()):
        adj_list.__delitem__(deleteIntegers[i])

That’s the result: {‘C’: {‘B’, 3, 4, ‘D’, ‘A’}, ‘B’: {‘C’, 4}, ‘A’: {‘C’, 2, ‘D’, 4}, ‘D’: {3, ‘C’, 2, ‘A’}}

I was hoping to obtain something like this: {‘C’: {‘B’: 4, ‘D’: 3, ‘A’: 4}, ‘B’: {‘C’: 4}, ‘A’: {‘D’: 2, ‘C’: 4}, etc. etc.

But as you can see the results are incorrect, and I can’t figure out how I can solve this problem. For example, I don’t understand how I can stop the for loop before it gets to the node’s weight and print it without sense, however then I would have to insert it afterwards to correctly display the distance between the starting and ending node.
But that is just one of the things I am not understanding and what is wrong with the program.
I’ve been banging my head about it for a while now and I’m not getting the hang of it, maybe I need a rest!
I haven’t been using python that long, so I still have a lot to learn.
Thank you so much in advance to anyone who answers me!

Asked By: CuloAtomico

||

Answers:

You can use a defaultdict:

from collections import defaultdict

graph_to_convert = [[('C', 'B', 4)], [('A', 'D', 2)], [('D', 'C', 3)], [('A', 'C', 4)]]
g = defaultdict(dict)

for edge in graph_to_convert:
    a,b,w = edge[0]
    g[a][b] = w

print(g)

#defaultdict(<class 'dict'>, {'C': {'B': 4}, 'A': {'D': 2, 'C': 4}, 'D': {'C': 3}})

If you aren’t happy with having a defaultdict as the final product, you can add the line g = dict(g) to cast the result to a straight dict.

Answered By: John Coleman
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.