讲师中心 微信公众号
AI工具推荐 视频效率加速

如何实现两个嵌套 dict 的结构化差异对比(不依赖 deepdiff)

夏枫大大_9521

夏枫大大_9521

发布时间:2026-01-28 17:15:09

|

837人浏览过

|

来源于php中文网

原创

推荐使用 dictdiffer 进行结构化 diff,它专为嵌套字典设计,输出可遍历的差异操作列表(add/change/remove),保留路径层级且精度高;需注意空值处理、不可哈希类型预过滤及忽略逻辑应置于存在性检查前。

如何实现两个嵌套 dict 的结构化差异对比(不依赖 deepdiff)

直接用 dictdiffer 做结构化 diff 最省心

它专为嵌套字典设计,输出是可遍历的差异操作列表(add、change、remove),不递归展开值,保留路径层级。比手写递归或用 json.dumps 字符串比对更准——后者会忽略键序、类型隐式转换、浮点精度等细节。

安装后直接调用:

from dictdiffer import diff<br>result = list(diff(dict_a, dict_b))
返回形如 [('change', ['user', 'profile', 'age'], (25, 26)), ('add', ['user', 'tags'], [('new', 'active')])] 的元组列表,路径用列表表示,改动类型和新旧值一目了然。

注意点:

  • dictdiffer 默认把 None 和缺失键视为不同,若想忽略空值差异,需预处理:把两边都转成统一缺省值(如 {} 或 None)再比
  • 对含自定义对象、函数、不可哈希类型的 dict 会抛 TypeError,得先用 copy.deepcopy + 类型过滤剥离

手动递归对比时必须处理路径追踪和类型分支

自己写递归不是不行,但容易漏掉三类关键逻辑:路径拼接错误、同键不同类型未区分、集合/列表内容顺序敏感性误判。核心是每层递归传入当前路径(如 ['config', 'database']),并在进入子结构前做类型校验。

示例关键判断逻辑:

def compare_dicts(d1, d2, path=None):<br>    if path is None:<br>        path = []<br>    for k in set(d1.keys()) | set(d2.keys()):<br>        cur_path = path + [k]<br>        if k not in d1:<br>            print(f"MISSING: {cur_path} in d1")<br>        elif k not in d2:<br>            print(f"MISSING: {cur_path} in d2")<br>        else:<br>            v1, v2 = d1[k], d2[k]<br>            if type(v1) != type(v2):<br>                print(f"TYPE_MISMATCH: {cur_path} — {type(v1).__name__} vs {type(v2).__name__}")<br>            elif isinstance(v1, dict) and isinstance(v2, dict):<br>                compare_dicts(v1, v2, cur_path)<br>            elif v1 != v2:<br>                print(f"VALUE_CHANGE: {cur_path} — {v1} → {v2}")

常见坑:

python 查询技能
python 查询技能

查询客流数据,输出JSON格式,可直接导入Bitable等可视化工具

下载
  • 用 str(path) 拼接路径导致嵌套列表变字符串,后续无法定位;必须保持 list 类型
  • 没判断 isinstance(v1, (list, tuple)) 就直接 ==,会把 [1,2] 和 (1,2) 判为相同
  • 对浮点数用 == 而非 math.isclose,小精度误差直接标为变更

用 deepdiff 以外的轻量替代:dictdiffer vs jsonpatch

jsonpatch 本质是生成符合 RFC 6902 的补丁操作,适合需要序列化、传输或回滚的场景;dictdiffer 更侧重人眼可读的结构差异。两者都不依赖 deepdiff,且体积小(jsonpatch 仅一个文件)。

选哪个?

  • 要生成可执行 patch 并应用到另一份数据上 → 用 jsonpatch.make_patch(dict_a, dict_b),输出是标准 JSON Patch 数组
  • 只需快速定位哪几层键变了、增删了哪些字段 → dictdiffer 返回原生 Python 结构,不用解析 JSON
  • 对比含 datetime、Decimal 等非 JSON 原生类型的 dict → 两者都会报错,必须先用 default 参数做序列化预处理

忽略某些键或路径时别硬编码,用白名单/黑名单函数

实际业务中常要忽略 updated_at、id、version 这类元字段。在 dictdiffer 或手写递归里,最稳的方式是传入一个 ignore_func,而不是在循环里写一堆 if k in ['id', 'version']。

例如:

def should_ignore(path):<br>    return any(<br>        p in ['id', 'updated_at', 'version'] for p in path<br>    ) or len(path) > 5  # 限制深度防止爆炸
然后在 diff 主逻辑中加判断:if should_ignore(cur_path): continue。

容易被忽略的点:

  • 路径是逐级累积的,['user', 'profile', 'id'] 中 'id' 在末尾,但 ['id'] 本身也可能是一级键,所以要用 any(...) 而非 path[-1] == 'id'
  • 忽略逻辑必须放在「键存在性检查之前」,否则 k not in d1 这类缺失判断也会被跳过,导致漏报真正缺失的字段

热门AI工具

更多
Lovart
Lovart Hot

一款面向视觉设计创作的AI设计平台,可通过智能体和画布工作流辅助制作海报、Logo、网页、PPT及其他视觉内容。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

PixPix
PixPix Hot

PixPix是一款面向电商视觉生产的AI商品图生成工具。

墨刀AI
墨刀AI Hot

一款AI图像与设计工具,主要用于产品经理的专属智能体,适合需要提升相关任务效率的用户。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

Laper
Laper Hot

Laper是专为编剧、导演和制片人推出的 AI 原生剧本创作工具。

讯飞绘文

讯飞绘文是一款由科大讯飞推出的一站式 AIGC 内容运营平台。

PixTV
PixTV Hot

PixTV是一款面向AIGC内容创作的AI视频生成工具。

相关专题

更多
json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

2095

2023.08.07

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

3142

2023.08.23

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

1056

2023.10.13

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

3579

2025.09.10

java break和continue
java break和continue

本专题整合了java break和continue的区别相关内容,阅读专题下面的文章了解更多详细内容。

747

2025.10.24

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

1698

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

2584

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

6004

2023.10.24

PHP 表单提交后如何获取数据
PHP 表单提交后如何获取数据

PHP表单提交后如何获取数据专题汇集HTML表单提交、GET与POST接收、$_POST和$_GET读取、跨文件传值、单选与下拉字段获取,以及空值和接收失败排查等文章,帮助新手完成从提交到处理的完整流程。

0

2026.10.15

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Uvicorn官方安装与入门手册
Uvicorn官方安装与入门手册

共0课时 | 0人学习

Python uv官方项目管理指南
Python uv官方项目管理指南

共0课时 | 0人学习

Python uv官方安装与入门文档
Python uv官方安装与入门文档

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn