如何用原生Python将3DS格式节点列表解析为嵌套Dict
用原生Python解析3DS自定义节点为嵌套字典
当然可以用原生Python实现这个解析需求!你的核心问题在于如何递归地识别键值对——尤其是处理那些多值属性和嵌套的子节点结构。我来帮你梳理思路并完善代码:
核心解析思路
我们需要一个递归函数来遍历输入的列表:
- 遍历过程中,遇到以
*开头的字符串时,将其作为字典的键 - 从当前位置开始,收集后续的元素作为值,直到遇到下一个以
*开头的键或者列表结束 - 如果收集到的元素是子列表,递归调用解析函数将其转为子字典
- 如果值的长度大于1,保留为列表;长度为1则直接取单个值;同时注意把字符串类型的数字转为数值类型(整数/浮点数)
完整实现代码
def parse_3ds_node(node_list): result = {} i = 0 length = len(node_list) while i < length: # 识别键:以*开头的字符串 if isinstance(node_list[i], str) and node_list[i].startswith('*'): key = node_list[i].strip('*') # 去掉开头的*作为键名 i += 1 values = [] # 收集值,直到遇到下一个键或者列表结束 while i < length and not (isinstance(node_list[i], str) and node_list[i].startswith('*')): item = node_list[i] # 如果是嵌套列表,递归解析为子字典 if isinstance(item, list): values.append(parse_3ds_node(item)) else: # 尝试转换为数值类型 try: # 先试整数,不行试浮点数 num_val = int(item) except ValueError: try: num_val = float(item) except ValueError: # 保留原始字符串(比如带引号的名称) num_val = item.strip('"') # 去掉引号 values.append(num_val) i += 1 # 处理值:单值直接赋值,多值保留列表 if len(values) == 1: result[key] = values[0] else: result[key] = values else: # 跳过非键的顶层元素(理论上输入结构不会有这种情况) i += 1 return result # 测试你提供的示例节点列表 sample_node = [['*NODE_NAME', '"30deg017"', '*CAMERA_TYPE', 'Target', '*NODE_TM', ['*NODE_NAME', '"30deg017"', '*INHERIT_POS', '0', '0', '0', '*INHERIT_ROT', '0', '0', '0', '*INHERIT_SCL', '1', '1', '1', '*TM_ROW0', '0.0939', '-0.9815', '-0.1668', '*TM_ROW1', '0.8819', '0.0043', '0.4714', '*TM_ROW2', '-0.4619', '-0.1913', '0.8660', '*TM_ROW3', '-230.9698', '-95.6709', '433.0127', '*TM_POS', '-230.9698', '-95.6709', '433.0127', '*TM_ROTAXIS', '-0.3314', '0.1476', '0.9319', '*TM_ROTANGLE', '1.5887', '*TM_SCALE', '1.0000', '1.0000', '1.0000', '*TM_SCALEAXIS', '0.9925', '-0.1222', '-0.0000', '*TM_SCALEAXISANG', '0.1253'], '*NODE_TM', ['*NODE_NAME', '"30deg017.Target"', '*INHERIT_POS', '0', '0', '0', '*INHERIT_ROT', '0', '0', '0', '*INHERIT_SCL', '0', '0', '0', '*TM_ROW0', '1.0000', '0.0000', '0.0000', '*TM_ROW1', '0.0000', '1.0000', '0.0000', '*TM_ROW2', '0.0000', '0.0000', '1.0000', '*TM_ROW3', '0.0000', '0.0000', '0.0000', '*TM_POS', '0.0000', '0.0000', '0.0000', '*TM_ROTAXIS', '0.0000', '0.0000', '0.0000', '*TM_ROTANGLE', '0.0000', '*TM_SCALE', '1.0000', '1.0000', '1.0000', '*TM_SCALEAXIS', '0.0000', '0.0000', '0.0000', '*TM_SCALEAXISANG', '0.0000'], '*CAMERA_SETTINGS', ['*TIMEVALUE', '0', '*CAMERA_NEAR', '0.0000', '*CAMERA_FAR', '1000000.0000', '*CAMERA_FOV', '1.1752', '*CAMERA_TDIST', '500.0000']]] # 注意示例是嵌套在一个列表里,所以取第一个元素解析 parsed_result = parse_3ds_node(sample_node[0]) import pprint pprint.pprint(parsed_result)
代码说明
- 递归处理嵌套结构:遇到子列表时,调用
parse_3ds_node递归解析,自动生成嵌套字典 - 数值类型转换:自动将字符串形式的整数、浮点数转为对应数值,同时保留带引号的节点名称(去掉引号)
- 键值配对逻辑:通过循环遍历,精准识别每个键对应的所有值,自动处理单值/多值场景
- 原生Python实现:完全不需要第三方库,依赖Python内置的类型判断和循环逻辑
测试输出示例
解析后的字典会像这样(部分展示):
{'CAMERA_SETTINGS': {'CAMERA_FAR': 1000000.0, 'CAMERA_FOV': 1.1752, 'CAMERA_NEAR': 0.0, 'CAMERA_TDIST': 500.0, 'TIMEVALUE': 0}, 'CAMERA_TYPE': 'Target', 'NODE_NAME': '30deg017', 'NODE_TM': [{'INHERIT_POS': [0, 0, 0], 'INHERIT_ROT': [0, 0, 0], 'INHERIT_SCL': [1, 1, 1], 'NODE_NAME': '30deg017', 'TM_POS': [-230.9698, -95.6709, 433.0127], ...}, {'INHERIT_POS': [0, 0, 0], 'INHERIT_ROT': [0, 0, 0], 'INHERIT_SCL': [0, 0, 0], 'NODE_NAME': '30deg017.Target', ...}]}
你可以把这个解析函数集成到你现有的AllCameras类里,替换掉原来的parse_node方法,就能完成完整的解析流程了。
内容的提问来源于stack exchange,提问作者James
相关产品推荐
相关产品推荐

