Godot中如何通过路径字符串动态读写嵌套Dictionary字典
GDScript动态操作嵌套字典实现方案
你之前拼接代码字符串调用str2var的方案不可行:str2var的作用是反序列化Godot格式的变体字符串,不会执行字符串里写的变量访问逻辑,所以拼出来的路径字符串没法直接用来操作字典。
另外你担心的“逐层传递引用破坏原字典结构”不成立:GDScript中Dictionary是引用类型,遍历过程中拿到的每一层子字典都是原字典对应位置的直接引用,对它做修改会直接同步到原字典,不会生成独立副本破坏结构。
通用工具函数
下面两个函数可以直接复用到你的项目里,支持斜杠分隔的路径格式,适配你当前LineEdit展示的路径规则:
# 传入根字典、斜杠分隔的路径字符串,返回路径对应的目标字典节点,路径非法时返回null func get_dict_node(root_dict: Dictionary, path_str: String): # 拆分路径并过滤空段,自动兼容首尾斜杠、连续斜杠的异常格式 var path_segments = path_str.split("/", false).filter(func(seg): return seg.strip_edges() != "") var current_node = root_dict for seg in path_segments: # 路径不存在对应键直接返回null if not current_node.has(seg): return null current_node = current_node[seg] # 中间节点不是字典类型说明路径非法,终止遍历 if typeof(current_node) != TYPE_DICTIONARY: return null return current_node # 传入根字典、父路径、新键名、新键对应的值,自动创建缺失的中间字典层级 func set_nested_value(root_dict: Dictionary, parent_path: String, new_key: String, value): var path_segments = parent_path.split("/", false).filter(func(seg): return seg.strip_edges() != "") var current_node = root_dict for seg in path_segments: # 中间层级不存在就自动创建空字典 if not current_node.has(seg) or typeof(current_node[seg]) != TYPE_DICTIONARY: current_node[seg] = {} current_node = current_node[seg] # 直接在父节点上添加新键,修改会同步到原根字典 current_node[new_key] = value
- 两个函数都自带路径格式兼容,不需要提前清洗LineEdit里的路径字符串
- 遍历过程全程操作引用,不会复制原字典产生冗余数据
替换你原有保存逻辑
你之前拼接dumb_string的代码可以全部删掉,直接调用工具函数即可完成新增子项操作:
print("saving subcategory") print(pathEdit.text) # 示例:在当前路径下新增名为string_1b的子分类,初始值为空字典 var parent_node = get_dict_node(Globals.notebook_data, pathEdit.text) if parent_node != null: parent_node["string_1b"] = {} # 如果需要自动补全不存在的父路径,直接调用set_nested_value即可 # set_nested_value(Globals.notebook_data, pathEdit.text, "string_1b", {})
优化原有路径生成函数
你之前提到删除数组0号元素会报错,原因是递归时数组按引用传递,多次insert操作会产生冗余空值。改成每次递归生成新数组,就不需要额外过滤空元素:
func update_path(object, full_path: Array = []): var current_text = object.get_text(0) var new_full_path = [current_text] + full_path var parent = object.get_parent() # 只有父节点存在get_text方法时才继续向上递归,避免把非路径UI节点算入路径 if parent != null and parent.has_method("get_text"): update_path(parent, new_full_path) else: pathEdit.text = "/".join(new_full_path) + "/"
内容的提问来源于stack exchange,提问作者Scott Ulmer
相关产品推荐
相关产品推荐

