如何基于已有anytree树构建新的Python anytree树?
基于anytree构建新树(不修改原树)
原树定义与结构
以下是原树的代码文件mytree.py:
# mytree.py import anytree as at import anytree.importer data = { "a": "root", "children": [ { "a": "sub0", "b": 3, "children": [{"a": "sub0A", "b": 9}, {"a": "sub0B", "b": 1}], }, {"a": "sub1", "b": 5}, ], } root = at.importer.DictImporter().import_(data)
执行命令进入交互模式:
python3 -i mytree.py
打印原树结构:
print(at.RenderTree(root, style=at.render.ContStyle())) # 输出: AnyNode(a='root') ├── AnyNode(a='sub0', b=3) │ ├── AnyNode(a='sub0A', b=9) │ └── AnyNode(a='sub0B', b=1) └── AnyNode(a='sub1', b=5)
需求说明
需要构建一个与原树结构完全一致的新树,要求:
- 新节点不含原树的
b属性 - 新增
c属性:原节点b值小于6时c为"small",大于等于6时为"large" - 全程不修改原树
尝试的遍历方式(未成功)
用户尝试用层序分组遍历,但未完成实现:
for on_this_level in at.LevelOrderGroupIter(root)
解决方案
方法1:递归遍历构建
递归遍历原树的每个节点,逐个创建新节点并设置对应属性,同时关联子节点:
import anytree as at def build_new_tree(original_node): # 计算c属性值(根节点没有b属性,默认设为small) c_val = "large" if hasattr(original_node, 'b') and original_node.b >= 6 else "small" # 创建新节点,仅保留a属性和新增c属性 new_node = at.AnyNode(a=original_node.a, c=c_val) # 递归处理子节点,将子节点的父节点设为当前新节点 for child in original_node.children: build_new_tree(child).parent = new_node return new_node # 生成新树 new_root = build_new_tree(root) # 验证新树结构 print(at.RenderTree(new_root, style=at.render.ContStyle()))
方法2:迭代式层序遍历构建
如果偏好迭代方式,可以用层序遍历(LevelOrderIter),同时维护原节点到新节点的映射,确保子节点能正确关联父节点:
import anytree as at # 用字典存储原节点到新节点的映射,方便快速查找父节点 node_mapping = {} # 层序遍历原树的所有节点 for original_node in at.LevelOrderIter(root): # 计算c属性值 c_val = "large" if hasattr(original_node, 'b') and original_node.b >= 6 else "small" # 创建新节点 new_node = at.AnyNode(a=original_node.a, c=c_val) node_mapping[original_node] = new_node # 根节点没有父节点,非根节点需要关联对应的父节点 if original_node.parent is not None: new_node.parent = node_mapping[original_node.parent] # 获取新树的根节点 new_root = node_mapping[root] # 验证新树结构 print(at.RenderTree(new_root, style=at.render.ContStyle()))
以上两种方式都不会对原树做任何修改,而是完全新建一个符合要求的树结构。
内容的提问来源于stack exchange,提问作者Daniel Diniz
相关产品推荐
相关产品推荐

