简体   繁体   中英

convert nested list to dictionary in python

It is not a strict nested list, it is a tree structure that looks like:

A = [a, [b, c,[d,e]]]

and the corresponding tree is :

                a
               / \
              b   c
                 / \                     
                 d e

Whenever there is a sublist after one element, the sublist corresponds to the child nodes of this element. Otherwise the elements are at the same layer. I want to generate a dictionary with each node as a key respectively, like:

child[a] = [b,c,d,e]
child[c] = [d,e]

How can I do that in python? Or is there other better suggestion on the tree structure conversion?

If you're going to be doing a lot of graph manipulation, I'd consider importing networkx , as it will make things easier. To parse your nested list into a networkx tree:

import networkx as nx

def parse_tree(node_list):
    """Parses a nested list into a networkx tree."""
    tree = nx.DiGraph()
    root = node_list[0]
    tree.add_node(root)

    queue = [(root, node_list[1])]

    while queue:
        parent, nodes = queue.pop(0)
        prev = None
        for node in nodes:
            if isinstance(node, list):
                queue.append((prev, node))
            else:
                tree.add_node(node)
                tree.add_edge(parent, node)

            prev = node

    return tree

With this function, it's simple to get a dictionary of the descendants of each node:

>>> l = ["a", ["b", "c",["d","e"]]]
>>> tree = parse_tree(l)
>>> {node: nx.descendants(tree, node) for node in tree}
{'a': {'b', 'c', 'd', 'e'},
 'b': set(),
 'c': {'d', 'e'},
 'd': set(),
 'e': set()}

I still think you should use / get inspired by an existing implementation, but this may be what you're looking for if you need this to work:

#!/usr/bin/env python

# added a test case
B = ['a', ['b', 'c',['d','e']], 'f', ['g', 'h']]
A = ['a', ['b', 'c',['d','e']]]

# found on stack overflow - flatten list of kids for parent
def flatten(iterable):
    """Recursively iterate lists and tuples.
    """
    for elm in iterable:
        if isinstance(elm, (list, tuple)):
            for relm in flatten(elm):
                yield relm
        else:
            yield elm

# add data to an existing tree (recursive)
def treeify(tree, l):
    if isinstance(l, list):
        # avoid looking back
        l.reverse()
    for index in range(len(l)):
        if isinstance(l[index], list):
            parent_name = l[index+1]
            # flatten kids to a list
            tree[parent_name] = list(flatten(l[index]))
            # continue in deeper lists
            treeify(tree, l[index])

tree = {}
treeify(tree, A)
print tree
tree = {}
treeify(tree, B)
print tree

this reverses the list to avoid looking back when traversing it. Tt sets the name as the next member if the current one is a list , and traverses the child elements immediately (recursively).

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM