【问题标题】:Algorithm to produce a clean __str__ method for a tree为树生成干净的 __str__ 方法的算法
【发布时间】:2019-10-29 13:39:04
【问题描述】:

我有一个 Tree 类,它由 Node 对象组成。每个Node 都有以下实例变量:

  • name: 节点的字符串名称
  • depth:树中节点深度的int(根深度为0)
  • parent:引用父对象Node(根的父对象是None
  • children:所有子 Node 对象的列表(叶子有一个空列表)

Node 类还有一个方法get_ancenstors(),它返回从Node 的父级到根的路径中的Nodes 列表。

树是使用递归函数构建的,并具有以下实例变量:

  • root:引用根Node
  • leaves:所有叶子列表Nodes

Tree 类有一个方法dfs(),它执行树的深度优先搜索/遍历并产生每个访问的Node。它也有一个__str__() 方法:

def __str__(self):
    string = ''
    for dir in self.dfs(self.root):
        # TODO: Create branches as '|-' 
        branches = ('  ' * (dir.depth))
        string += f'{branches}{dir.name}\n'
    return string

产生如下输出:

Dir 1
  Dir 2
    Dir 3
  Dir 4
    Dir 5
      Dir 6
      Dir 7
    Dir 8
  Dir 9
    Dir 10

相反,我想要这个__str__() 方法的视觉更清晰但更复杂的实现,它会产生如下输出:

Dir 1
|--- Dir 2
|    |--- Dir 3
|
|--- Dir 4
|    |--- Dir 5
|    |    |--- Dir 6
|    |    |--- Dir 7
|    |
|    |--- Dir 8
|
|--- Dir 9
     |--- Dir 10
     |--- Dir 11
          |--- Dir 12

谁能帮忙解释一下这背后的逻辑?

【问题讨论】:

    标签: python recursion tree


    【解决方案1】:

    使用以下具有特定格式逻辑的解决方案:

    def __str__(self):
        string = ''
        for dir in self.dfs(self.root):
            branches, depth = '', dir.depth
            if depth > 0:
                branches = '|--- '  # initial (closest) dashed block
                branches = '|    ' * (depth - 1) + branches
            string += f'{branches}{dir.name}\n'
        return string
    

    演示的简化测试用例:

    from collections import namedtuple
    
    Node = namedtuple('Node', 'name depth')
    dfs = [Node(f'Dir{i+1}', depth=i) for i in range(4)]
    
    def n__str__(dfs):
        string = ''
        for dir in dfs:
            branches, depth = '', dir.depth
            if depth > 0:
                branches = '|--- '  # initial (closest) dashed block
                branches = '|    ' * (depth - 1) + branches
            string += f'{branches}{dir.name}\n'
        return string
    
    print(n__str__(dfs))
    

    输出:

    Dir1
    |--- Dir2
    |    |--- Dir3
    |    |    |--- Dir4
    

    【讨论】:

      【解决方案2】:

      一种可能性是创建一个递归生成器,为每个孩子生成一个完整的行。然后,在__str__,你可以简单地使用str.join

      class Tree:
         ...
         def to_dir(self, d = 0, flag=True):
            if flag:
              yield self.name if not d else '|'+"|".join(["\t"]*(d-1))+f'{"|"*(bool(d-1))}--- {self.name}'
            else:
               yield "".join(["\t"]*(d-1))+f'{"|"*(not d)}{"|"*(bool(d))}--- {self.name}'
            for i, a in enumerate(self.children):
               yield from a.to_dir(d=d+1, flag = falg)
         def __str__(self):
            return '\n'.join(self.to_dir())
      

      例子:

      class Tree:
         def __init__(self, n, c):
            self.name, self.children = n, c
         def to_dir(self, d = 0, flag=True): 
            if flag:
               yield self.name if not d else '|'+"|".join(["\t"]*(d-1))+f'{"|"*(bool(d-1))}--- {self.name}'
            else:
               yield "".join(["\t"]*(d-1))+f'{"|"*(not d)}{"|"*(bool(d))}--- {self.name}'
            for i, a in enumerate(self.children):
               yield from a.to_dir(d=d+1, flag=False if not flag else i != len(self.children)-1)
         def __str__(self):
            return '\n'.join(self.to_dir())
      
      t = Tree('Dir 1', [Tree('Dir 2', [Tree('Dir 5', [])]), Tree('Dir 3', []), Tree('Dir 4', [Tree('Dir 6', [Tree('Dir 7', [])])])])
      

      输出:

      Dir 1
      |--- Dir 2
             |--- Dir 5
      |--- Dir 3
      |--- Dir 4
             |--- Dir 6
                    |--- Dir 7
      

      【讨论】:

        猜你喜欢
        • 2021-12-19
        • 2015-12-23
        • 2011-03-12
        • 1970-01-01
        • 2018-11-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-01
        相关资源
        最近更新 更多