Я посмотрел на anytree
и придумал это:
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
.
, результат действительно
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