作为一个时间传递活动,我决定在python中实现一个Tree(like)结构
我实现了一个Node
类(仅此处用于此目的),如下所示:
class Node:
def __init__(self, name, parent, *data):
self.name = name
self.parent = parent
self.data = data
self.children = []
self.is_root = False
def __repr__(self):
return 'Node '+repr(self.name)
def dic(self):
retval = {self:[]}
for i in self.children:
retval[self].append(i.dic())
return retval
def display(self): # Here
pass
def has_children(self):
return bool(self.children)
def get_parent(self):
return self.parent
def add_child(self, name, *data):
child = Node(name, self,*data)
self.children.append(child)
return child
如您所见,display
功能尚未实施
这是一个示例树。
A = Node('A',Node)
A.is_root = True
B = A.add_child('B')
D = B.add_child('D')
C = A.add_child('C')
E = C.add_child('E')
F = C.add_child('F')
G = C.add_child('G')
以下是display
的一些示例输出。
>>> A.display()
A
+-^-+
B C
| +-+-+
D E F G
>>> C.display()
C
+-+-+
E F G
以最短的形式,
如何从Node类“构建”ASCII树(如上所述)
更长的形式,
印刷的“逻辑”是:
|
被放在孩子的上方。 (d)+
,(B,C,E,F)^
被置于父母之下。 (A)+
放在父母之下。 (C)我一直在考虑从下面开始。 我意识到必须给每个孩子打个电话,但是他们无法实现任何接近它的任何东西(那种或其他)。
答案 0 :(得分:13)
这是一个涵盖您正在寻找的大部分内容的解决方案。
与任何树算法一样,递归树的子项,并在每个节点处组合结果。这是诀窍:display()
返回一个文本矩形,例如:
aaaaaa
aaaaaa
aaaaaa
大多数矩形都是空格。仅返回文本的矩形使得组合结果变得容易。我们将使用以下两个辅助函数,一个用于测量块宽度,另一个用于将块水平组合成更大的块:
def block_width(block):
try:
return block.index('\n')
except ValueError:
return len(block)
def stack_str_blocks(blocks):
"""Takes a list of multiline strings, and stacks them horizontally.
For example, given 'aaa\naaa' and 'bbbb\nbbbb', it returns
'aaa bbbb\naaa bbbb'. As in:
'aaa + 'bbbb = 'aaa bbbb
aaa' bbbb' aaa bbbb'
Each block must be rectangular (all lines are the same length), but blocks
can be different sizes.
"""
builder = []
block_lens = [block_width(bl) for bl in blocks]
split_blocks = [bl.split('\n') for bl in blocks]
for line_list in itertools.izip_longest(*split_blocks, fillvalue=None):
for i, line in enumerate(line_list):
if line is None:
builder.append(' ' * block_lens[i])
else:
builder.append(line)
if i != len(line_list) - 1:
builder.append(' ') # Padding
builder.append('\n')
return ''.join(builder[:-1])
看看这是怎么回事?子元素返回一个显示自身及其后代的矩形,每个节点将这些矩形组合成一个包含自身的较大矩形。其余的代码只是渲染破折号:
class Node:
def display(self): # Here
if not self.children:
return self.name
child_strs = [child.display() for child in self.children]
child_widths = [block_width(s) for s in child_strs]
# How wide is this block?
display_width = max(len(self.name),
sum(child_widths) + len(child_widths) - 1)
# Determines midpoints of child blocks
child_midpoints = []
child_end = 0
for width in child_widths:
child_midpoints.append(child_end + (width // 2))
child_end += width + 1
# Builds up the brace, using the child midpoints
brace_builder = []
for i in xrange(display_width):
if i < child_midpoints[0] or i > child_midpoints[-1]:
brace_builder.append(' ')
elif i in child_midpoints:
brace_builder.append('+')
else:
brace_builder.append('-')
brace = ''.join(brace_builder)
name_str = '{:^{}}'.format(self.name, display_width)
below = stack_str_blocks(child_strs)
return name_str + '\n' + brace + '\n' + below
# SNIP (your other methods)
我们参加了比赛!
a
+-+-+---------------------------+
b e f g
+ +-+-------------------------+
c h i k
+ + +-+-+-+-------------+-------------+-+------+
d j l m p r s O P Q
+ + +-+-+-+---------+ +-----+
n q t u w x y R S
+ + +-------+-------+ +---+---+
o v z A M T U Z
+-+-+-+-+-+-+ + + +
B D E H I K L N V a
+ + + +-+-+ +
C F J W X Y b
+
G
(诸如“将^放在父母之下”的要求留作读者的练习)
答案 1 :(得分:2)
我想建议看一下ETE模块http://ete.cgenomics.org,它实现了你在这里描述的功能等等。
与此同时,我想提供此条目Pretty Print output in a sideways tree format in console window,之前已经提出了类似的问题。正如您在此类讨论中所看到的,ETE的_asciiArt函数提供了我认为您正在寻找的内容。
我希望这有帮助,