0

0

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

冰川箭仙

冰川箭仙

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

|

817人浏览过

|

来源于php中文网

原创

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

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

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

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

安装后直接调用:

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

常见坑:

PNG Maker
PNG Maker

利用 PNG Maker AI 将文本转换为 PNG 图像。

下载
  • 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_atidversion 这类元字段。在 dictdiffer 或手写递归里,最稳的方式是传入一个 ignore_func,而不是在循环里写一堆 if k in ['id', 'version']

例如:

def should_ignore(path):
return any(
p in ['id', 'updated_at', 'version'] for p in path
) 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工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

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

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

418

2023.08.07

json是什么
json是什么

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

535

2023.08.23

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

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

311

2023.10.13

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

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

77

2025.09.10

if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

776

2023.08.22

java break和continue
java break和continue

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

256

2025.10.24

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

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

298

2023.08.03

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

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

212

2023.09.04

俄罗斯Yandex引擎入口
俄罗斯Yandex引擎入口

2026年俄罗斯Yandex搜索引擎最新入口汇总,涵盖免登录、多语言支持、无广告视频播放及本地化服务等核心功能。阅读专题下面的文章了解更多详细内容。

158

2026.01.28

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 22.3万人学习

Django 教程
Django 教程

共28课时 | 3.6万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.3万人学习

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

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号