【问题标题】:Rendering a Tree in Python在 Python 中渲染树
【发布时间】:2018-01-16 07:28:05
【问题描述】:

我有如下数据集:

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 在这里很有用,但我不知道如何实现这段代码。任何帮助将不胜感激。

【问题讨论】:

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


    【解决方案1】:

    使用字典(如果需要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))
    

    【讨论】:

      【解决方案2】:

      您当前的输出[[1], [1, 2], [1, 2, 5], [1, 2, 5, 3], [1, 2, 6], [1, 2, 6, 7], [1, 2, 4]] 是一个扁平列表。第一步是将其折叠成树形结构。然后你可以通过一个简单的装饰器来渲染它。 (以下代码使用 Python 3.6.1 测试)

      # 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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-11-01
        • 2015-03-25
        • 1970-01-01
        • 2017-02-13
        • 2012-07-08
        • 1970-01-01
        • 1970-01-01
        • 2011-01-10
        相关资源
        最近更新 更多