0

我正在尝试实现一个树,每个“部分”节点具有唯一 ID,每个部分中的每个子节点都有唯一 ID。我想知道如何用anytree (python). 我试过这个:

from anytree import AnyNode, RenderTree, Resolver


class MyTree:

    def create(self):
        self.root = AnyNode(id="root")
        initial_section_node = AnyNode(id="section1", parent=self.root)
        AnyNode(id="sub0A", parent=initial_section_node)
        AnyNode(id="sub0B", parent=initial_section_node)
        another_section_node = AnyNode(id="section2", parent=self.root)
        AnyNode(id="sub0A", parent=another_section_node)
        AnyNode(id="sub0B", parent=another_section_node)

    def add_node_to_parent(self, section_id, node_id: str):
        r = Resolver("id")
        section_node = r.get(self.root, section_id)
        if node_id not in section_node.children:
            AnyNode(id=node_id, parent=section_node)
        else:
            print(node_id + " already exists")

    def display(self):
        print(RenderTree(self.root))


test_tree = MyTree()
test_tree.create()
test_tree.add_node_to_parent("section1", "sub0C")
test_tree.add_node_to_parent("section1", "sub0A")  # this will add another node with this id, but I want to prevent this
test_tree.display()

但它显示

AnyNode(id='root')
├── AnyNode(id='section1')
│   ├── AnyNode(id='sub0A')
│   ├── AnyNode(id='sub0B')
│   ├── AnyNode(id='sub0C')
│   └── AnyNode(id='sub0A')
└── AnyNode(id='section2')
    ├── AnyNode(id='sub0A')
    └── AnyNode(id='sub0B')

即,我可以使用解析器找到正确的部分,然后向其中添加新节点,但条件if node_id not in section_node.children:不起作用,因为node_id不是节点对象而是字符串对象。

我知道我需要再次使用解析器来检查“section1”节点的子节点是否具有我要添加的 ID,但我更喜欢使用集合section_node.children,因为我认为它比解析器工作得更快,尤其是大树。

4

2 回答 2

1

正如您所说,您不能直接检查 astring中是否包含 a tupleof objects。您可以定义一个函数,例如

if not list(filter(lambda x:x.id==node.id, section_node.children)):

但我怀疑这会比Resolver.

或者,您可以处理自定义属性children_ids,并将其用于检查。

于 2021-09-29T21:01:58.740 回答
0

我找到了一个可能的解决方案。我们可以使用解析器中找到的节节点(而不是整个根节点)来查找子节点。修改后的 add_node_to_parent 函数如下所示:

def add_node_to_parent(self, section_id, node_id: str):
    r = Resolver("id")
    section_node = r.get(self.root, section_id)
    try:
        node = r.get(section_node, node_id)
        print(node_id + " already exists")
    except anytree.resolver.ChildResolverError:
        AnyNode(id=node_id, parent=section_node)

现在,输出符合预期:

sub0A already exists
AnyNode(id='root')
├── AnyNode(id='section1')
│   ├── AnyNode(id='sub0A')
│   ├── AnyNode(id='sub0B')
│   └── AnyNode(id='sub0C')
└── AnyNode(id='section2')
    ├── AnyNode(id='sub0A')
    └── AnyNode(id='sub0B')

当然,如果没有找到section_id ,该行r.get(self.root, section_id)也可以引发异常,但答案说明了原理。ChildResolverError

于 2021-09-29T17:43:36.423 回答