使用anytree从带有缩进的文件生成树
Generate tree from file with indents using anytree
我正在使用 anytree 从文件 Tree.txt
生成树。每个缩进为 3 个空格 (
)。这是我的文件的样子:
ROOT
Node1
Node2
Node3
Node4
Node5
Node6
这里是我到目前为止的生成代码:
from anytree import Node, RenderTree, find_by_attr
def parse_tree():
with open('Tree.txt', 'r') as file:
file_contents = file.readlines()
root = Node("ROOT")
current_indent = -1 # store index for comparing later
for (index, line) in enumerate(file_contents):
leading_spaces = len(line) - len(line.lstrip(' '))
indent = int(leading_spaces / 3) # indent = 3 spaces
if indent > current_indent: # node must be 1 level down
# get the previous Node (1 level up)
previous_line = file_contents[index - 1].strip()
current_line = line.strip()
parent = find_by_attr(root, previous_line)
Node(current_line, parent=parent) # start searching from top node (root) for `previous_line`
current_indent = indent
else: # node is on same level or higher
print(f"What to do for {line.strip()}?")
# what should I do here?
print(RenderTree(root)) # print the output
parse_tree()
然而,这打印出来:
What to do for Node5?
What to do for Node6?
Node('/ROOT')
└── Node('/ROOT/Node1')
└── Node('/ROOT/Node1/Node2')
└── Node('/ROOT/Node1/Node2/Node3')
└── Node('/ROOT/Node1/Node2/Node3/Node4')
生成的树很好,但直到 Node4
- Node5
和 Node6
丢失。这是意料之中的,因为我没有处理当前缩进小于前一个缩进的情况(参见 # what should I do here?
)。
当前缩进小于上一个缩进怎么办?我知道我需要升到更高的 n
级别,但我如何知道那是哪个级别?
您需要一种堆栈来跟踪节点的深度,然后您可以使用初始空间的数量来确定将每个叶子追加到哪个父节点。例如,三个空格表示向下一层,因此您需要追加到堆栈中索引 0 处的根节点。 (你也可以说,通过使用堆栈,我们正在获取叶子的 绝对 深度,而你试图解决它 relatively 如果我'我说得通)。我怀疑如果你使用 find_by_attr
,如果有同名的叶子,那可能不起作用。
treestring = '''
ROOT
Node1
Node2
Node3
Node4
Node5
Node6'''.strip()
leaves = treestring.splitlines()
# initialize stack with the root node
stack = {0: Node(leaves.pop(0))}
for leaf in leaves:
# determine the node's depth
leading_spaces = len(leaf)-len(leaf.lstrip(' '))
level = int(leading_spaces/3)
# add the node to the stack, set as parent the node that's one level up
stack[level] = Node(leaf.strip(), parent=stack[level-1])
tree = stack[0]
for pre, _, node in RenderTree(tree):
print(f"{pre}{node.name}")
结果:
ROOT
├── Node1
│ └── Node2
│ └── Node3
│ └── Node4
├── Node5
└── Node6
我正在使用 anytree 从文件 Tree.txt
生成树。每个缩进为 3 个空格 (
)。这是我的文件的样子:
ROOT
Node1
Node2
Node3
Node4
Node5
Node6
这里是我到目前为止的生成代码:
from anytree import Node, RenderTree, find_by_attr
def parse_tree():
with open('Tree.txt', 'r') as file:
file_contents = file.readlines()
root = Node("ROOT")
current_indent = -1 # store index for comparing later
for (index, line) in enumerate(file_contents):
leading_spaces = len(line) - len(line.lstrip(' '))
indent = int(leading_spaces / 3) # indent = 3 spaces
if indent > current_indent: # node must be 1 level down
# get the previous Node (1 level up)
previous_line = file_contents[index - 1].strip()
current_line = line.strip()
parent = find_by_attr(root, previous_line)
Node(current_line, parent=parent) # start searching from top node (root) for `previous_line`
current_indent = indent
else: # node is on same level or higher
print(f"What to do for {line.strip()}?")
# what should I do here?
print(RenderTree(root)) # print the output
parse_tree()
然而,这打印出来:
What to do for Node5?
What to do for Node6?
Node('/ROOT')
└── Node('/ROOT/Node1')
└── Node('/ROOT/Node1/Node2')
└── Node('/ROOT/Node1/Node2/Node3')
└── Node('/ROOT/Node1/Node2/Node3/Node4')
生成的树很好,但直到 Node4
- Node5
和 Node6
丢失。这是意料之中的,因为我没有处理当前缩进小于前一个缩进的情况(参见 # what should I do here?
)。
当前缩进小于上一个缩进怎么办?我知道我需要升到更高的 n
级别,但我如何知道那是哪个级别?
您需要一种堆栈来跟踪节点的深度,然后您可以使用初始空间的数量来确定将每个叶子追加到哪个父节点。例如,三个空格表示向下一层,因此您需要追加到堆栈中索引 0 处的根节点。 (你也可以说,通过使用堆栈,我们正在获取叶子的 绝对 深度,而你试图解决它 relatively 如果我'我说得通)。我怀疑如果你使用 find_by_attr
,如果有同名的叶子,那可能不起作用。
treestring = '''
ROOT
Node1
Node2
Node3
Node4
Node5
Node6'''.strip()
leaves = treestring.splitlines()
# initialize stack with the root node
stack = {0: Node(leaves.pop(0))}
for leaf in leaves:
# determine the node's depth
leading_spaces = len(leaf)-len(leaf.lstrip(' '))
level = int(leading_spaces/3)
# add the node to the stack, set as parent the node that's one level up
stack[level] = Node(leaf.strip(), parent=stack[level-1])
tree = stack[0]
for pre, _, node in RenderTree(tree):
print(f"{pre}{node.name}")
结果:
ROOT
├── Node1
│ └── Node2
│ └── Node3
│ └── Node4
├── Node5
└── Node6