在Python中渲染树

时间:2018-01-16 07:28:06

标签: python python-3.x recursion tree anytree

我有如下数据集:

A    B

1    2
5    3
2    5
3    

下面的代码给出了以下输出:

def all_paths(table, root):
    # convert table structure to adjacency list
    children = {}
    for node, child in table:
        if child: 
             children[node] = children.setdefault(node, []) + [child]

        # generator for iteration over all paths from a certain node
        def recurse(path):
            yield path
            if path[-1] in children:
                for child in children[path[-1]]: # recursive calls for all child nodes
                    yield from recurse(path + [child])

        return recurse([root])

# Sample data in simple list format    
table = [
[1, 2],
[5, 3],
[2, 5],
[2, 6],
[2, 4],
[6, 7],
]

# Output all paths from node 1
for path in all_paths(table, 1):
    print(path)

Output: 
[1]
[1, 2]
[1, 2, 5]
[1, 2, 5, 3]
[1, 2, 6]
[1, 2, 6, 7]
[1, 2, 4]

但我想要的是以渲染树格式打印输出,如下所示:

1
└── 2
    |── 5
    |   └──3 
    |── 6
    |   └──7
    └── 4

我知道python库Anytree在这里很有用,但我不知道如何实现这段代码。任何帮助都将受到高度赞赏。

2 个答案:

答案 0 :(得分:0)

您当前的输出# to fold a tree you need first to get the leave for each flattened branch at proper levels # toleavel([1,2,5]) --> [[[5]]] def toleave(branch): if branch[1:] == []: return [branch[0]] else: return [toleave(branch[1:])] # fold the flattened tree def fold(flattened_tree): if flattened_tree == []: return [] else: return toleave(flattened_tree[0]) + fold(flattened_tree[1:]) # decorator for rendering def render(f): render.level = -2 indent = ' ' def _f(*args): render.level += 1 try: result = f(*args) if not isinstance(result, list): print(render.level*indent, result) finally: render.level = -2 return result return _f # go over a tree and render it @render def tree_render(tree): if not isinstance(tree, list): return tree elif tree == []: return [] else: return [tree_render(tree[0])] + [tree_render(tree[1:])] flattened_tree = [[1], [1, 2], [1, 2, 5], [1, 2, 5, 3], [1, 2, 6], [1, 2, 6, 7], [1, 2, 4]] tree_render(fold(flattened_tree)) # output: # 1 # 2 # 5 # 3 # 6 # 7 # 4 是一个展平列表。第一步是将其折叠成树形结构。然后你可以通过一个简单的装饰器渲染它。 (下面的代码用Python 3.6.1测试)

{{1}}

答案 1 :(得分:0)

使用字典(如果需要collections.OrderedDict)将使循环更容易。 使用推荐的anytree包,它将提供所需的图形输出,整个代码将只是:

import anytree

# parent-child relations
table = [
    [1, 2],
    [5, 3],
    [2, 5],
    [2, 6],
    [2, 4],
    [6, 7],
]

def build_tree_recursively(p_num, p_node):
    for c_num in parent_children[p_num]:  # add children
        c_node = anytree.Node(str(c_num), parent=p_node)
        if c_num in parent_children:  # dive into
            build_tree_recursively(c_num, c_node)

# map parents to list of children
parent_children = {}
for p, c in table:  # numbers
    if p in parent_children:
        parent_children[p].append(c)
    else:
        parent_children[p] = [c]

p = 1  # assuming single root node (else add loop over elements not in column B)
tree = anytree.Node(str(p))
build_tree_recursively(p, tree)

# render
for pre, fill, node in anytree.RenderTree(tree):
    print("{}{}".format(pre, node.name))