You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何更新含嵌套字典列表的嵌套字典(列表元素顺序无关)

深度嵌套字典(含嵌套字典的列表)的正确更新实现

问题背景

我有多个不同深度的嵌套字典,具备以下特性:

  • 字典可包含内部嵌套进一步字典的列表;
  • 字典也可包含仅存值的“叶子列表”;
  • 列表元素顺序无关。

示例数据

base_d = {'level 1' : {'level 2': [{'level 3': [1,2,3], 'level 4': {'level 6': 'replace_me'} } ] } }

update_d = {'level 1' : {'level 2': [{'level 4': {'level 6': 'new_value','level 7':456},'level 5':123  , 'level 3': [1,2,3,4] }] } }

预期更新结果

希望用update_d更新base_d后得到:

new_d = {'level 1' : {'level 2': [{'level 3': [1,2,3,4], 'level 4': {'level 6': 'new_value'} } ] } }

尝试过的方法及问题

1. pydantic.utils.deep_update

使用该方法得到的结果不符合预期:

from pydantic.utils import deep_update

result = deep_update(base_d, update_d)
# 输出:
{'level 1': {'level 2': [{'level 4': {'level 6': 'new_value', 'level 7': 456}, 'level 5': 123, 'level 3': [1, 2, 3, 4]}]}}

问题:保留了update_d中新增的level 7和level 5,但实际预期只更新原有键对应的值,不新增未在base_d中出现的键。

2. 自定义更新函数

import collections

def update(orig_dict, new_dict):
    for key, val in new_dict.iteritems():
        if isinstance(val, collections.abc.Mapping):
            tmp = update(orig_dict.get(key, { }), val)
            orig_dict[key] = tmp
        elif isinstance(val, list):
            orig_dict[key] = (orig_dict.get(key, []) + val)
        else:
            orig_dict[key] = new_dict[key]
    return orig_dict

问题:无法正确处理列表内部的嵌套字典更新逻辑。

解决方案

要实现符合预期的更新,需针对列表中的嵌套字典做特殊处理:识别列表中结构匹配的字典(通过键集合交集判断),对其进行深度更新而非直接替换/合并列表;同时,字典更新仅覆盖原有键的值,不新增原字典中不存在的键。

以下是实现函数:

import collections.abc

def deep_update_filtered(orig, update):
    if isinstance(orig, collections.abc.Mapping) and isinstance(update, collections.abc.Mapping):
        # 仅遍历原字典已存在的键,避免新增未定义的键
        for key in orig:
            if key in update:
                orig[key] = deep_update_filtered(orig[key], update[key])
        return orig
    elif isinstance(orig, list) and isinstance(update, list):
        # 处理含嵌套字典的列表:匹配同结构字典进行更新
        for orig_item in orig:
            for update_item in update:
                if isinstance(orig_item, collections.abc.Mapping) and isinstance(update_item, collections.abc.Mapping):
                    # 存在共同键则视为同一实体,递归更新
                    if set(orig_item.keys()) & set(update_item.keys()):
                        deep_update_filtered(orig_item, update_item)
        # 处理叶子列表:合并去重(因顺序无关)
        if not any(isinstance(item, collections.abc.Mapping) for item in orig + update):
            orig[:] = list(set(orig + update))
        return orig
    else:
        # 基础类型直接用更新值替换
        return update

测试验证

base_d = {'level 1' : {'level 2': [{'level 3': [1,2,3], 'level 4': {'level 6': 'replace_me'} } ] } }
update_d = {'level 1' : {'level 2': [{'level 4': {'level 6': 'new_value','level 7':456},'level 5':123  , 'level 3': [1,2,3,4] }] } }

result = deep_update_filtered(base_d, update_d)
print(result)
# 输出与预期一致:
{'level 1': {'level 2': [{'level 3': [1, 2, 3, 4], 'level 4': {'level 6': 'new_value'}}]}}

函数说明

  1. 字典处理:仅遍历原字典已有的键,用更新字典对应键的值递归更新,不会新增原字典中不存在的键;
  2. 列表处理:
    • 嵌套字典列表:通过键交集匹配同实体字典,递归更新内部结构;
    • 叶子列表:合并两个列表并去重(因顺序无关);
  3. 基础类型:直接用更新值替换原值。

内容的提问来源于stack exchange,提问作者Kspr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 07:25:24