【问题标题】:Adding new nodes by id in anytree在anytree中按id添加新节点
【发布时间】:2021-09-29 15:26:32
【问题描述】:

我正在尝试实现一棵树,每个“节”节点都有唯一的 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,因为我认为它比解析器运行得更快,尤其是对于大树。

【问题讨论】:

    标签: python search nodes anytree


    【解决方案1】:

    正如您所说,您不能直接检查 string 是否包含在 tupleobjects 中。你可以定义一个函数,例如

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

    但我怀疑这会比Resolver 更快。

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

    【讨论】:

    • 是的,lambda 也可以解决问题。谢谢你。我想知道解析器如何(快速)在引擎盖下进行搜索。
    【解决方案2】:

    我找到了一个可能的解决方案。我们可以使用解析器中找到的节节点(而不是整个根节点)来查找子节点。修改后的 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')
    

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

    【讨论】:

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