I'm trying to create an arbitrarily nested dictionary from a list of key, value pairs in Python. The list of key value pairs looks like this:
input_data = [{1:2}, {2:3}, {3:4}, {3:5}, {1:3}]
[My actual input data is much larger and has much more recursion.] Given that input, the goal is to nest all key value pairs, so that one achieves:
{1: {2: {3: {4: null}, {5: null}}}, {3: {4: null, 5: null} } }
I have been tinkering with some recursive functions but still haven't hit a breakthrough. If others have ideas that could help solve this kind of nesting problem, I'd be very grateful for their suggestions.
You can do this in a 2 step process, first convert the list of edges to a graph of node to connected nodes:
In []:
graph = {}
for edge in inpt:
for n1, n2 in edge.items():
graph.setdefault(n1, []).append(n2)
graph
Out[]
{1: [2, 3], 2: [3], 3: [4, 5]}
Note: don't use input
as a variable name it hides python's builtin input()
Then it is reasonably easy to create a recursive function to get the paths you are looking for, here's a recursive function that takes a graph and starting node and returns the paths from that node:
In []:
def paths(graph, nodes):
if not nodes:
return None
return {node: paths(graph, graph.get(node, [])) for node in nodes}
paths(graph, [1])
Out[]
{1: {2: {3: {4: None, 5: None}}, 3: {4: None, 5: None}}}
Note: your expected output isn't a valid dictionary
Or you can do this iteratively using a queue:
In []:
def paths(graph, start):
p = {}
q = [(start, p, set())]
while q:
node, c, visited = q.pop()
if node not in graph or node in visited:
c[node] = None
continue
visited = visited | {node}
for n in graph[node]:
q.append((n, c.setdefault(node, {}), visited))
return p
paths(graph, 1)
Out[]:
{1: {2: {3: {4: None, 5: None}}, 3: {4: None, 5: None}}}
Note: this requires a directed non-cyclical graph or it will recurse until python fails - which would need additional checks to avoid.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.