【问题标题】:convert nested list to dictionary in python在python中将嵌套列表转换为字典
【发布时间】:2014-12-11 00:41:23
【问题描述】:

它不是一个严格的嵌套列表,它是一个看起来像这样的树结构:

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

对应的树是:

                a
               / \
              b   c
                 / \                     
                 d e

只要一个元素后面有一个子列表,这个子列表就对应这个元素的子节点。否则元素在同一层。我想分别以每个节点为键生成一个字典,例如:

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

如何在 python 中做到这一点?或者有没有其他更好的关于树形结构转换的建议?

【问题讨论】:

  • 重复键会发生什么,例如[a, [b, a,[d,e]]]?结果如何?尝试使用现有的树实现并使用它。
  • @ReutSharabani 感谢 Reut。所有元素都是不同的。

标签: python list parsing dictionary tree


【解决方案1】:

如果您要进行大量图形操作,我会考虑导入networkx,因为它会使事情变得更容易。将嵌套列表解析为 networkx 树:

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

通过这个函数,可以很简单的得到每个节点的后代字典:

>>> 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()}

【讨论】:

    【解决方案2】:

    我仍然认为您应该使用现有实现/从现有实现中获得灵感,但如果您需要它来工作,这可能是您正在寻找的:

    #!/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
    

    这会反转 list 以避免在遍历它时回头。如果当前成员是list,Tt 将名称设置为下一个成员,并立即(递归)遍历子元素。

    【讨论】:

      猜你喜欢
      • 2020-05-16
      • 2021-09-25
      • 1970-01-01
      • 1970-01-01
      • 2023-03-11
      • 2022-12-05
      • 2020-09-03
      • 1970-01-01
      相关资源
      最近更新 更多