【问题标题】:Printing a numbered outline of a hierarchical tree打印分层树的编号轮廓
【发布时间】:2014-01-13 11:00:03
【问题描述】:

我正在尝试编写一个函数来打印带有十进制轮廓编号的对象层次结构树(在 Blender 3D 中,但这是一个通用的 Python 问题)。

我需要:

  • 带有任何符号的可选缩进,例如"+""--" 或没有缩进"",以及
  • 一个可选的附加 ".0" 到具有子节点的节点以区分分支和叶子。

例如,在 Blender 中,我创建了一个带有骨骼和层次结构的骨架,如下所示:

+ Life
++ Bacteria
++ Eukaryota
+++ plants
+++ animals
++++ Vertebrates
+++++ amphibians
+++++ reptiles
+++++ mammals

在 de Text Editor 中,我创建了这个基本脚本:

import bpy
D = bpy.data
root = D.armatures['Armature'].bones['Life']

def print_hierarchy(obj, indent = "+"):
    print(indent, obj.name)
    for child in obj.children:
        print_hierarchy(child, indent+"+")
print_hierarchy(root)

此脚本输出:

+ Life
++ Bacteria
++ Eukaryota
+++ plants
+++ animals
++++ Vertebrates
+++++ amphibians
+++++ reptiles
+++++ mammals

我希望它看起来像这样

1.0 Life
    1.1 Bacteria
    1.2.0 Eukaryota
        1.2.1 plants
        1.2.2.0 animals
            1.2.2.1.0 Vertebrates
                1.2.2.1.1 amphibians
                1.2.2.1.2 reptiles
                1.2.2.1.3 mammals

我已经修改了(递归)函数print_hierarchy(),但每次我尝试向其添加新内容时它都会中断。我想不通,所以我需要一些帮助。

对于这类事情,while 循环是否比递归函数更好/更有效/更快?

【问题讨论】:

    标签: python-3.x blender


    【解决方案1】:

    这样做会更容易,例如

    1 Life
        1.1 Bacteria
        1.2 Eukaryota
            1.2.1 plants
            1.2.2 animals
                  1.2.2.1 Vertebrates
                  1.2.2.1.1 amphibians
                  1.2.2.1.2 reptiles
                  1.2.2.1.3 mammals
    

    这样你就不必明确地检查节点是否有子节点print 它了。一些有用的代码:

    for index, child in enumerate(obj.children, 1):
    

    这将使用从 1 开始的索引对每个 children 进行编号。

    ''.join(('\t', indent, '.', str(index)))
    

    在前一个 indent 的开头添加一个新选项卡,在末尾添加一个 index。把它们放在一起:

    def print_hierarchy(root, indent="1"):
        print('\t'.join([indent, root.name]))
        for index, child in enumerate(root.children, 1):
            print_hierarchy(child, ''.join(('\t', indent, '.', str(index))))
    

    我明白了:

    1   life
        1.1 bacteria
        1.2 eukaryota
            1.2.1   plants
            1.2.2   animals
                1.2.2.1 vertebrates
                    1.2.2.1.1   amphibians
                    1.2.2.1.2   reptiles
                    1.2.2.1.3   mammals
    

    为了更完整的功能,它变得更复杂:

    def print_hierarchy(root, indent=None, dec=None, zeroes=False):
        if indent is None:
            indent = []
        elif isinstance(indent, str):
            indent = [indent]
        if dec is None:
            dec = []
            zeroes = False
        elif isinstance(dec, int):
            dec = [str(dec)]
        elif isinstance(dec, str):
            dec = [dec]
        print(' '.join([''.join(indent), 
                        '.'.join(dec + ["0"] if root.children and zeroes else dec), 
                        root.name]))
        for index, child in enumerate(root.children, 1):
            print_hierarchy(child, 
                            indent + [indent[0]] if indent else indent, 
                            dec + [str(index)] if dec else dec,
                            zeroes)
    
    print_hierarchy(root, "\t", 1, True)
    

    【讨论】:

    • 您可以使用enumerate(seq, 1) 使索引从1 开始,而不是0
    【解决方案2】:

    你可以像这样改变你的递归函数:

    >>> def print_hierarchy(obj, prefix = ''):
            print('{}{} {}'.format(prefix, '.0' if obj.children else '', obj.name))
            for num, child in enumerate(obj.children, 1):
                print_hierarchy(child, '    {}.{}'.format(prefix, num))
    
    >>> print_hierarchy(root, '1')
    1.0 Life
        1.1 Bacteria
        1.2.0 Eukaryota
            1.2.1 plants
            1.2.2.0 animals
                1.2.2.1.0 Vertebratens
                    1.2.2.1.1 amphibians
                    1.2.2.1.2 reptiles
                    1.2.2.1.3 mammals
    

    但我同意 jonrsharpe 的观点,编号对于层次结构并没有真正意义。这使得LifeBacteria 似乎处于同一水平,但Eukaryota 不是。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-28
      • 2017-01-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-15
      • 2022-11-20
      相关资源
      最近更新 更多