Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 从具有重复子树的嵌套列表构造树视图(使用anytree/treelib)_Python_Python 3.x_Tree_Treeview_Anytree - Fatal编程技术网

Python 从具有重复子树的嵌套列表构造树视图(使用anytree/treelib)

Python 从具有重复子树的嵌套列表构造树视图(使用anytree/treelib),python,python-3.x,tree,treeview,anytree,Python,Python 3.x,Tree,Treeview,Anytree,我有一个嵌套列表,如下所示: lst = [['a', 'b', 'e'], # this e is the branch of b ['a', 'f', 'e'], # this e is the branch of f, ['a', 'h', 'i i i']] # string with spaces 我想建造一棵树,就像: a ├── b │ └── e ├── f | └── e └── h └── i i i 我想

我有一个嵌套列表,如下所示:

lst = [['a', 'b', 'e'],      # this e is the branch of b
       ['a', 'f', 'e'],      # this e is the branch of f,
       ['a', 'h', 'i i i']]  # string with spaces
我想建造一棵树,就像:

a
├── b
│   └── e
├── f
|   └── e
└── h
    └── i i i
我想使用两个包中的任何一个:和。我读过很多帖子,尝试过很多不同的方法,但都没有成功

更新:

我想出了以下方法,但我现在遇到的问题是

  • 分支的垂直顺序(例如,“b”、“f”、“h”)不保证(当我在一个列表中有许多列表时)
  • “e”作为“f”的分支不会出现
  • 我调查并得出了以下结论:

    from anytree import Node, RenderTree
    
    lst = [["a", "b", "c", "e"], ["a", "b", "f"], ["a", "b", "c", "g", "h"], ["a", "i"]]
    
    
    def list_to_anytree(lst):
        root_name = lst[0][0]
        root_node = Node(root_name)
        nodes = {root_name: root_node}  # keeping a dict of the nodes
        for branch in lst:
            assert branch[0] == root_name
            for parent_name, node_name in zip(branch, branch[1:]):
                node = nodes.setdefault(node_name, Node(node_name))
                parent_node = nodes[parent_name]
                if node.parent is not None:
                    assert node.parent.name == parent_name
                else:
                    node.parent = parent_node
        return root_node
    
    
    anytree = list_to_anytree(lst)
    for pre, fill, node in RenderTree(anytree):
        print(f"{pre}{node.name}")
    
    这里发生的事情不多。我只是将列表转换为任意树节点(执行此操作时,列表表示是有效的)。我在
    节点中保留了一个节点字典

    产出确实很高

    a
    ├── b
    │   ├── c
    │   │   ├── e
    │   │   └── g
    │   │       └── h
    │   └── f
    └── i
    

    如果您有多个同名节点,则不能使用上面的
    dict
    ;您需要从根节点迭代子节点:

    def list_to_anytree(lst):
        root_name = lst[0][0]
        root_node = Node(root_name)
        for branch in lst:
            parent_node = root_node
            assert branch[0] == parent_node.name
            for cur_node_name in branch[1:]:
                cur_node = next(
                    (node for node in parent_node.children if node.name == cur_node_name),
                    None,
                )
                if cur_node is None:
                    cur_node = Node(cur_node_name, parent=parent_node)
                parent_node = cur_node
        return root_node
    
    你的榜样

    lst = [
        ["a", "b", "e"],  # this e is the branch of b
        ["a", "f", "e"],  # this e is the branch of f,
        ["a", "h", "i i i"],
    ]
    
    anytree = list_to_anytree(lst)
    for pre, fill, node in RenderTree(anytree):
        print(f"{pre}{node.name}")
    
    然后给出:

    a
    ├── b
    │   └── e
    ├── f
    │   └── e
    └── h
        └── i i i
    

    嗨,伙计。由于某些原因,我不断得到一个带有空格字符串的AssertError。你能看看我最新的问题吗?嗨,史蒂文!问题不在于具有空格的节点,而是有两个名为
    e
    的节点具有不同的父节点。如果不需要考虑这一点,我需要稍微更改一下逻辑(我的
    节点
    字典将无法工作…)。嗨,伙计。有没有其他方法可以使用next()来缩短代码?据我所知,没有。。。例如,请参见以下内容:。您可以将其打包到一个函数中(将其分解):
    def next\u child(cur\u node\u name,parent\u node):return next(…)
    a
    ├── b
    │   └── e
    ├── f
    │   └── e
    └── h
        └── i i i