如何用for循环构建可变深度的嵌套字典?(基于Pandas层级数据)
问题描述
现有一个数千行的Pandas表格,行首空格数决定该行是否为上一行的子结构,表格示例如下:
Parameter | Value 'country' 'Germany' ' city' 'Berlin' ' area' 'A1' ' city' 'Munchen' ' comment' 'a comment' 'country' 'France' ' city' 'Paris' ' comment' 'a comment' 'state' 'California' ' comment' '123'
同时已知参数是否为列表的配置:
{ 'country': list, 'city': list, 'state': list }
目标是生成如下嵌套结构:
{ "country": [ { "Germany": { "city": [ { "Berlin": { "area": "A1" } }, { "Munchen": { "comment": "a comment" } } ] } }, { "France": { "city": [ { "Paris": { "comment": "a comment" } } ] } } ], "state": [ { "California": { "comment": 123 } } ] }
尝试用for循环实现,但无法判断循环中是新增列表元素还是进入已有元素,现有代码输出不符合预期。
现有尝试代码
import pandas as pd import itertools # 原代码遗漏导入 params = ['country',' city',' area',' city',' comment','country',' city',' comment','state',' comment'] vals = ['Germany','Berlin','A1','Munich','acomment','France','Paris','acomment','California','123'] conf = {'country':'list','city':'list'} # 配置遗漏state参数及逗号 df = pd.DataFrame() df['param'] = params df['vals']= vals output_dict = dict() level_path = dict() for param,vals in df.values: d = output_dict hiearchy_level = sum( 1 for _ in itertools.takewhile(str.isspace,param)) param = param.lstrip() if hiearchy_level > 0: base_path = level_path[str(hiearchy_level-1)] else: base_path = [] path = base_path + [param] for p in path: if p in conf: d.setdefault(p,[{}]) d = d[p][-1] else: d.setdefault(p,{}) d = d[p] d[param] = vals level_path[str(hiearchy_level)] = path
现有错误输出
{'country': [{'country': 'France', 'city': [{'city': 'Paris', 'area': {'area': 'A1'}, 'comment': {'comment': 'a comment'}}]}], 'state': {'state': 'California', 'comment': {'comment': '123'}}}
解决思路与修正代码
核心问题分析
- 混淆了参数名与参数值的层级关系:目标结构是
{参数名: [{参数值: {子结构}}]},原代码直接将参数名作为键存储值,导致结构错乱 - 未判断新增列表元素的时机:同层级出现同名参数时,需新增列表项而非复用已有元素
- 层级跟踪方式错误:仅保存参数路径无法直接定位操作节点,应保存每个层级对应的实际字典/列表对象
修正后实现逻辑
- 维护
level_nodes字典,存储每个层级当前对应的操作节点(字典或列表) - 处理每行时,先计算层级并获取父节点
- 若当前参数为列表类型:
- 在父节点中初始化该参数的列表
- 新增
{参数值: {}}结构到列表中 - 将当前操作节点指向该结构的子字典
- 若为非列表类型,直接在父节点下设置键值对
- 更新
level_nodes,保存当前层级的操作节点
修正后的代码
import pandas as pd import itertools params = ['country',' city',' area',' city',' comment','country',' city',' comment','state',' comment'] vals = ['Germany','Berlin','A1','Munich','a comment','France','Paris','a comment','California','123'] # 修正配置,与目标结构匹配 conf = {'country': list, 'city': list, 'state': list} df = pd.DataFrame({'param': params, 'vals': vals}) output_dict = {} # 存储每个层级当前对应的操作节点 level_nodes = {} for idx, row in df.iterrows(): param_raw = row['param'] val = row['vals'] # 计算当前层级(行首空格数) level = sum(1 for _ in itertools.takewhile(str.isspace, param_raw)) param = param_raw.lstrip() # 获取父节点 if level == 0: parent_node = output_dict else: parent_node = level_nodes[level - 1] if param in conf: # 当前参数为列表类型,新增列表项 parent_node.setdefault(param, []) new_item = {val: {}} parent_node[param].append(new_item) # 切换到当前参数值对应的子字典 current_node = new_item[val] else: # 非列表类型,直接设置键值对 parent_node[param] = val # 若后续有子节点,父节点即为当前参数所在的字典 current_node = parent_node # 更新当前层级的操作节点 level_nodes[level] = current_node print(output_dict)
最终输出结果
{ 'country': [ {'Germany': {'city': [{'Berlin': {'area': 'A1'}}, {'Munich': {'comment': 'a comment'}}]}}, {'France': {'city': [{'Paris': {'comment': 'a comment'}}]}} ], 'state': [{'California': {'comment': '123'}}] }
内容的提问来源于stack exchange,提问作者Kspr
相关产品推荐
相关产品推荐

