如何在python中显示类似于msdos tree命令的树?
考虑一下这个mcve:如何在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
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