从具有重复子树的嵌套列表构建树视图(使用 anytree/treelib) [英] constructing a tree view from a nested list with duplicate subtrees (using anytree/treelib)
问题描述
我有一个如下所示的嵌套列表:
I have a nested list like the following:
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
我想构建一棵树,例如:
and I wanna to construct a tree like:
a
├── b
│ └── e
├── f
| └── e
└── h
└── i i i
我想使用两个包中的任何一个:treelib 和 anytree.我读了很多帖子,尝试了很多不同的方法,但都没有成功.
I want to use either of the two packages: treelib and anytree. I've read many posts and tried many different methods and didn't make it work.
更新:
我想出了以下方法,但我现在遇到的问题是
I came up with the following method, but the problems I have now are
- 不能保证分支的垂直顺序(例如,b"、f"、h")(当我在一个列表中有很多列表时).
- e"作为f"的分支不会出现
from treelib import Node, Tree
# make list flat
lst = sum([i for i in lst], [])
tree = Tree()
tree_dict = {}
# create root node
tree_dict[lst[0]] = tree.create_node(lst[0])
for index, item in enumerate(lst[1:], start=1):
if item not in tree_dict.keys():
partent_node = tree_dict[lst[index-1]]
tree_dict[item] = tree.create_node(item, parent=partent_node)
tree.show()
推荐答案
我查看了 anytree
并想出了这个:
i looked into anytree
and came up with this:
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}")
这里没有发生太多事情.我只是将您的列表转换为 anytree 节点(并且 assert
这样做时列表表示是有效的).并且我在 nodes
中保留了我已经拥有的节点的字典.
there is not much happening here. i just convert your list to anytree nodes (and assert
the list representation is valid while doing that). and i keep a dictionary of the nodes i already have in nodes
.
输出确实是
a
├── b
│ ├── c
│ │ ├── e
│ │ └── g
│ │ └── h
│ └── f
└── i
<小时>
如果你有多个同名的节点,你就不能使用上面的dict
;您需要从根节点遍历子节点:
if you have multiple nodes with the same name you can not use the dict
above; you need to iterate from the root node over the children:
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
这篇关于从具有重复子树的嵌套列表构建树视图(使用 anytree/treelib)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!