如何在python中显示类似于msdos tree命令的树?

如何在python中显示类似于msdos tree命令的树?,python,tree,Python,Tree,考虑一下这个mcve: import sys dct = { -1: [0, 60000], 0: [100, 20], 100: [30], 30: [400, 500], 60000: [70, 80] } def ptree(parent, tree, indent=''): print(parent) if parent not in tree: return for child in tree[p

考虑一下这个mcve:

import sys


dct = {
    -1: [0, 60000],
    0: [100, 20],
    100: [30],
    30: [400, 500],
    60000: [70, 80]
}


def ptree(parent, tree, indent=''):
    print(parent)
    if parent not in tree:
        return

    for child in tree[parent][:-1]:
        print(indent + '|' + '-' * 4, end='')
        ptree(child, tree, indent + '|' + ' ' * 4)
    child = tree[parent][-1]
    print(indent + '`' + '-' * 4, end='')
    ptree(child, tree, indent + '  ' * 4)


ptree(-1, dct)
这个小代码有两个问题:

  • 在本文中,项-1被视为“不可见的根项”,因此我不想打印它
  • 这个命令的输出非常难看,对齐也不好,我希望得到一个与
为了解决第一个要点,我考虑在代码中引入这些丑陋的条件/攻击:

def ptree(parent, tree, indent=''):
    if parent != -1:
        print(parent)
    if parent not in tree:
        return

    for child in tree[parent][:-1]:
        if parent != -1:
            print(indent + '|' + '-' * 4, end='')
            ptree(child, tree, indent + '|' + ' ' * 4)
        else:
            ptree(child, tree, indent)
    child = tree[parent][-1]
    if parent != -1:
        print(indent + '`' + '-' * 4, end='')
        ptree(child, tree, indent + '  ' * 4)
    else:
        ptree(child, tree, indent)
对于第二个bulletpoint,我不知道如何实现它,但msdos tree命令显示的输出非常好,我希望我的命令以完全相同的方式显示树,下面是命令的示例:


问题:如何调整上述代码,使其正确处理上述两个要点?

第一个问题很简单:检查父值;如果是-1,不要打印它

缩进量是根据节点值的打印图像移动的问题,而不是恒定的4个空格。
math
包有
log10
ceil
方法来完成这项工作

import sys
import math


dct = {
    -1: [0, 60000],
    0: [100, 20, 7],
    100: [30],
    30: [400, 500],
    60000: [70, 80],
    7: [9, 11, 13],
}


def ptree(parent, tree, indent=''):

    if parent != -1:
        print(parent)

    if parent not in tree:
        return

    shift = math.ceil(math.log10(parent)) \
            if parent >= 10 else 1
    indent += ' ' * shift

    for child in tree[parent][:-1]:
        print(indent + '|' + '-' * 4, end='')
        ptree(child, tree, indent + '|' + ' ' * 4)

    child = tree[parent][-1]
    print(indent + '`' + '-' * 4, end='')
    ptree(child, tree, indent + ' ' * 4)


ptree(-1, dct)
输出:

 |----0
 |     |----100
 |     |      `----30
 |     |            |----400
 |     |            `----500
 |     |----20
 |     `----7
 |          |----9
 |          |----11
 |          `----13
 `----60000
          |----70
          `----80

通过反复试验,我终于找到了一个解决方案,它似乎准确地说出了原始树产生的结果:

def ptree(start, tree, indent_width=4):

    def _ptree(start, parent, tree, grandpa=None, indent=""):
        if parent != start:
            if grandpa is None:  # Ask grandpa kids!
                print(parent, end="")
            else:
                print(parent)
        if parent not in tree:
            return
        for child in tree[parent][:-1]:
            print(indent + "├" + "─" * indent_width, end="")
            _ptree(start, child, tree, parent, indent + "│" + " " * 4)
        child = tree[parent][-1]
        print(indent + "└" + "─" * indent_width, end="")
        _ptree(start, child, tree, parent, indent + " " * 5)  # 4 -> 5

    parent = start
    _ptree(start, parent, tree)


dct = {
    -1: [0, 60000],
    0: [100, 20, 10],
    100: [30],
    30: [400, 500],
    60000: [70, 80, 600],
    500: [495, 496, 497]
}
除了使用正确的连接器外,检查是否有外公,并将上次ptree调用的缩进从4增加到5也是关键



你是想得到一些有用的东西,还是想知道如何自己写?因为PyPI上有很多库已经在做类似的事情了。我模糊地记得使用了一个名为
asciitree
(可能是,但我不认为是;我记得有选项指定要使用哪一组划线字符…),您可以搜索其他字符。
treelib
模块看起来很有希望,实际上,我对
asciitree
的看法是错误的,它确实有我记得的选项。看,伙计们,谢谢你们提供这些库的链接,明天我一定会去看看,我通常喜欢自己写这类东西,但在这种情况下,我真的不介意使用一些现成的东西。主要的先决条件是解决方案提供了一个令人愉快的输出,我将使用进程树,我的第一个想法是,像msdos tree命令提供的输出非常令人愉快,因为行是连续的(不分散注意力)。谢谢你的回答,这当然是一个有趣的方法,起初,我认为固定宽度的缩进,比如msdos-tree命令提供的缩进,确实令人赏心悦目,但您的方法看起来也没那么糟糕,是吗?顺便说一句,您知道哪些字符使用msdos树命令而不是{'`、'-'、'|'}字符集吗?这样,树的线条看起来是连续的。明天,我将用长嵌套树彻底测试您的答案,以检查与固定宽度缩进方法相比的感觉,目前为+1。@darknoaut真棒!我真的很喜欢这个答案。ascitree和treelib都是很好的候选者,但没有找到跳过根节点的方法。普伦姆的回答是好的,但缺少连续的几行。另外,相比之下,我认为这一个是非常方便的工作,我认为有固定的宽度水平有几点优势。所以,是的,谢谢;)顺便说一句,似乎算法在使用值时无法正确打印树=-1,即:尝试显示这些值的树
0100,3050060000
,以了解将起始节点值从-1更改为另一个值是什么意思?您是否也更改了此行中的值:
if parent!=-1:
?谢谢,就这样。顺便说一句,我想公共签名应该变成更像
def ptree(父、树、键、级别)
的东西,其中键是一个过滤函数,并且是
4
5
常量值的a级参数化。仔细想想,
grandge
indent
只是私有变量,因此不应该向用户公开。无论如何,再次感谢你指出你是对的,一个包装是有意义的,不仅仅是这样。如果你想放大,也可以添加一个起始值参数,这样你就不必更改代码了……我现在就做最后一个。
ptree(-1, dct)
# Out
├────0
│    ├────100
│    │    └────30
│    │         ├────400
│    │         └────500
│    │              ├────495
│    │              ├────496
│    │              └────497
│    ├────20
│    └────10
└────60000
     ├────70
     ├────80
     └────600