在Python中打印树形数据结构

28

我正在寻找一种可能的树形打印实现,可以将树以用户友好的方式打印出来,而不是作为对象的实例。

我在网络上找到了这个解决方案:

来源: http://cbio.ufs.ac.za/live_docs/nbn_tut/trees.html

class node(object):
    def __init__(self, value, children = []):
        self.value = value
        self.children = children

    def __repr__(self, level=0):
        ret = "\t"*level+repr(self.value)+"\n"
        for child in self.children:
            ret += child.__repr__(level+1)
        return ret

这段代码以以下方式打印树:

'grandmother'
    'daughter'
        'granddaughter'
        'grandson'
    'son'
        'granddaughter'
        'grandson'

有没有可能在不改变__repr__方法的情况下获得相同的结果,因为我正在将其用于另一个目的。

4个回答

40
是的,将__repr__代码移动到__str__中,然后在树上调用str()或将其传递给print语句。记得在递归调用中也要使用__str__
class node(object):
    def __init__(self, value, children = []):
        self.value = value
        self.children = children

    def __str__(self, level=0):
        ret = "\t"*level+repr(self.value)+"\n"
        for child in self.children:
            ret += child.__str__(level+1)
        return ret

    def __repr__(self):
        return '<tree node representation>'

演示:

>>> root = node('grandmother')
>>> root.children = [node('daughter'), node('son')]
>>> root.children[0].children = [node('granddaughter'), node('grandson')]
>>> root.children[1].children = [node('granddaughter'), node('grandson')]
>>> root
<tree node representation>
>>> str(root)
"'grandmother'\n\t'daughter'\n\t\t'granddaughter'\n\t\t'grandson'\n\t'son'\n\t\t'granddaughter'\n\t\t'grandson'\n"
>>> print root
'grandmother'
    'daughter'
        'granddaughter'
        'grandson'
    'son'
        'granddaughter'
        'grandson'

1
@WolfgangKuehne:当然,使用不同的函数名称(在两个位置重命名),并使用print '\t' * level + repr(self.value)而不是构建ret值。这是101递归。 - Martijn Pieters

5
为什么不将其存储为treelib对象并打印出与您的用例相关的更相关节点描述,类似于我们在此处打印CHAID树的方式?
([], {0: 809, 1: 500}, (sex, p=1.47145310169e-81, chi=365.886947811, groups=[['female'], ['male']]))
├── (['female'], {0: 127, 1: 339}, (embarked, p=9.17624191599e-07, chi=24.0936494474, groups=[['C', '<missing>'], ['Q', 'S']]))
│   ├── (['C', '<missing>'], {0: 11, 1: 104}, <Invalid Chaid Split>)
│   └── (['Q', 'S'], {0: 116, 1: 235}, <Invalid Chaid Split>)
└── (['male'], {0: 682, 1: 161}, (embarked, p=5.017855245e-05, chi=16.4413525404, groups=[['C'], ['Q', 'S']]))
    ├── (['C'], {0: 109, 1: 48}, <Invalid Chaid Split>)
    └── (['Q', 'S'], {0: 573, 1: 113}, <Invalid Chaid Split>)

3
一个简单的解决方案是打印pathlib.Path对象:
from pathlib import Path

def print_tree(p: Path, last=True, header=''):
    elbow = "└──"
    pipe = "│  "
    tee = "├──"
    blank = "   "
    print(header + (elbow if last else tee) + p.name)
    if p.is_dir():
        children = list(p.iterdir())
        for i, c in enumerate(children):
            print_tree(c, header=header + (blank if last else pipe), last=i == len(children) - 1)

print_tree(Path("./MNE-001-2014-bids-cache"))

输出:

└──MNE-001-2014-bids-cache
   ├──sub-1
   │  ├──ses-E
   │  │  ├──sub-1_ses-E_scans.tsv
   │  │  └──eeg
   │  │     ├──sub-1_ses-E_task-imagery_run-5_desc-b3b3d5ec2913316a996cc197966c5862_events.tsv
   │  │     ├──sub-1_ses-E_space-CapTrak_electrodes.tsv
   │  │     ├──sub-1_ses-E_task-imagery_run-0_desc-b3b3d5ec2913316a996cc197966c5862_eeg.json
   │  │     ├──sub-1_ses-E_task-imagery_run-1_desc-b3b3d5ec2913316a996cc197966c5862_eeg.edf
   │  │     └──sub-1_ses-E_task-imagery_run-2_desc-b3b3d5ec2913316a996cc197966c5862_channels.tsv
   │  ├──sub-1_desc-b3b3d5ec2913316a996cc197966c5862_lockfile.json
   │  └──ses-T
   │     ├──sub-1_ses-T_scans.tsv
   │     └──eeg
   │        ├──sub-1_ses-T_task-imagery_run-3_desc-b3b3d5ec2913316a996cc197966c5862_eeg.json
   │        ├──sub-1_ses-T_task-imagery_run-3_desc-b3b3d5ec2913316a996cc197966c5862_eeg.edf
   │        ├──sub-1_ses-T_task-imagery_run-0_desc-b3b3d5ec2913316a996cc197966c5862_events.tsv
   │        └──sub-1_ses-T_task-imagery_run-4_desc-b3b3d5ec2913316a996cc197966c5862_eeg.edf
   ├──README
   ├──dataset_description.json
   ├──participants.json
   └──participants.tsv

0

不修改__repr____str__的解决方案

def other_name(self, level=0):
    print('\t' * level + repr(self.value))
    for child in self.children:
        child.other_name(level + 1)

这个答案是由OP Kristof Pal 在CC BY-SA 3.0下发布的,作为编辑问题在Python中打印树形数据结构的回答。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接