【问题标题】:Print tree with indentations打印带有缩进的树
【发布时间】:2016-03-17 15:53:35
【问题描述】:

我想打印一棵描述乐队的简单树。我首先创建一个名为“Band”的节点,然后创建子“Wind instruments”,依次生成子“Saxophone”和“Trumpet”。然后我为“管乐器”制作了一个兄弟,称为“歌曲”等等。代码非常简单:

class Node:                                     
    value = ""
    down = None
    right = None
def write(p):
    if p==None:
        return
    print(p.value)
    if p.down!=None:        #My idea is that if we go down the tree, we indent first
        print("    ",end="")     
        write(p.down)
    write(p.right)      #If we don't go down, we simply write out the siblings
a=Node()
a.value="Band"
a.down=Node()
a.down.value="Wind instruments"
a.down.down=Node()
a.down.down.value="Saxophone"
a.down.down.right=Node()
a.down.down.right.value="Trumpet"
a.down.right=Node()
a.down.right.value="Song"
a.down.right.right=Node()
a.down.right.right.value="String instruments"
a.down.right.right.down=Node()
a.down.right.right.down.value="Guitar"
a.down.right.right.down.right=Node()
a.down.right.right.down.right.value="Bass"
write(a)

输出是:

Band
    Wind instruments
    Saxophone
Trumpet
Song
String instruments
    Guitar
Bass

但我希望输出是:

Band
    Wind instruments
        Saxophone
        Trumpet
    Song
    String instruments
        Guitar
        Bass

有人知道如何实现这一目标吗?

【问题讨论】:

  • 区分类变量和属性!在初始化 Node() valuedownright 之后,类变量对于所有实例都是相同的。通过分配一个值,您将这三个添加为作为每个实例的单独变量的属性。您可以通过a = Node(); print(a.__dict__); a.value = 3; print(a.__dict__)查看。对于树木,请参见 e。 G。 openbookproject.net/thinkcs/python/english2e/ch21.html

标签: python python-3.x


【解决方案1】:

要根据递归级别进行缩进打印,诀窍是使用一个参数来保持递归时所处的级别:

# default with a level of 0, and an indent of 4 characters
def write(p, depth=0, indent=4):
    if p==None:
        return
    # here we multiply the level by the number of indents
    # and then you multiply that number with a space character
    # which will magically show as that number of spaces.
    print("{}{}".format(" "*(indent*depth), p.value))
    if p.down!=None:
        # then you do not need your print(…, end='') hack
        # simply increase the depth
        write(p.down, depth=depth+1, indent=indent)
    # and for siblings, do not increase the depth
    write(p.right, depth=depth, indent=indent)

我在这里使用的技巧是,默认情况下,级别为 0,随着您的深入,您通过传递增加 1 的参数来增加深度。

然后,当您想要打印缩进时,您所要做的就是将缩进字符串乘以该值(以及缩进大小),然后您就可以随意打印缩进:

>>> "A"*42
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'

结果:

>>> write(a)
Band
    Wind instruments
        Saxophone
        Trumpet
    Song
    String instruments
        Guitar
        Bass

如果你想让它更窄,因为你有很多递归:

>>> write(a, indent=1)
Band
 Wind instruments
  Saxophone
  Trumpet
 Song
 String instruments
  Guitar
  Bass

作为奖励,我建议您将 write() 函数设为 Node 类的方法。如果你把它重命名为__str__:

class Node:
    value = ""
    down = None
    right = None

    # converts a node into a string
    def as_str(self, depth=0, indent=4):
        # building the current node's line, and add it to a list
        ret = ["{}{}".format(" "*(indent*depth), self.value)]
        if self.down:
            # append down recursion first to the list
            ret.append(self.down.as_str(depth=depth+1, indent=indent))
        if self.right:
            # then append right recursion to the list
            ret.append(self.right.as_str(depth=depth, indent=indent))
        # build the new string, joining each element of the list with a newline
        return "\n".join(ret)

    # a handler for printing the list nicely
    def __str__(self):
        return self.as_str()

    def as_repr(self, depth=0, max_depth=2):
        # building the current node's line, and add it to a list
        ret = ["'{}'".format(self.value)]
        if depth > max_depth:
            ret.append("…")
        else:
            if self.down:
                # append down recursion first to the list
                ret.append(self.down.as_repr(depth=depth+1, max_depth=max_depth))
            if self.right:
                # then append right recursion to the list
                ret.append(self.right.as_repr(depth=depth, max_depth=max_depth))
            # build the new string, joining each element of the list with a newline
        return "Node<{}>".format(",".join(ret))

    # you might want to also make the repr() nicer
    def __repr__(self):
        return self.as_repr()

结果:

>>> a
Node<'Band',Node<'Wind instruments',Node<'Saxophone',…>,Node<'Song',Node<'String instruments',Node<'Guitar',…>>>>>
>>> print(a)
Band
    Wind instruments
        Saxophone
        Trumpet
    Song
    String instruments
        Guitar
        Bass

HTH

【讨论】:

  • 我不认识这个位:"{}{}",format(...) 您能否详细说明它的作用?否则一切都清楚了!
  • cf documentation 这是处理字符串格式的新的首选方法。最基本的用法是,对于您提供给format() 的每个参数,它将以相同的顺序替换{} 标记。它相当于旧式字符串格式:"%s%s" % (" "*indent*level, p.value).
  • 不会 print(" "*depth * indent,p.value) 做同样的事情吗??
  • 不,因为print("A", "B") 给出了"A B",因为它在print() 函数的每个参数之间添加了一个额外的空格,所以你的缩进计数是错误的。另外,使用字符串格式可以帮助你构建一个字符串,当你想构建一个返回的字符串时(参见我的第二个 sn-p),你可以保持相同的代码。
  • 非常好!作为一个额外的好处,它可以返回一个字符串,然后可以打印,写入文件等。只需添加一个输出参数,然后将每一行附加到它。
【解决方案2】:

引入一个输入参数i来控制要打印的缩进数。

def write(p, i = 1):
    if p==None:
        return
    print(p.value)  
    j = i   # store No. of current indent to j
    if p.down!=None:    # process p.down 
        for ii in range(i):
            print("    ",end="")
        i += 1          # No. of indent + 1
        write(p.down, i)
    if p.right!=None:   # process p.right
        for jj in range(j - 1):
            print("    ",end="")
        write(p.right, j)   #No. of indent keep same 

运行:

write(a) 

结果:

Band
    Wind instruments
        Saxophone
        Trumpet
    Song
    String instruments
        Guitar
        Bass

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多