如何让DeepDiff输出差异时显示对应数据的ID字段?
解决DeepDiff对比列表数据时显示ID而非索引的问题
问题背景
我使用DeepDiff对比两个数据库数据,示例代码如下:
from deepdiff import DeepDiff users1 = [{'id': 1, 'name': 'John', 'age': 30}, {'id': 2, 'name': 'Jane', 'age': 25}] users2 = [{'id': 1, 'name': 'John', 'age': 30}, {'id': 2, 'name': 'Bob', 'age': 35}] diff = DeepDiff(users1, users2) print(diff)
当前输出仅显示列表索引,无法直接对应到数据的ID:
{'values_changed': {"root[0]['age']": {'new_value': 20, 'old_value': 30}, "root[1]['name']": {'new_value': 'Bob', 'old_value': 'Jane'}, "root[1]['age']": {'new_value': 35, 'old_value': 25}}}
希望输出中能显示对应数据的ID值,明确是哪个ID的记录出现字段差异,比如将路径中的索引替换为ID,或者按ID分组展示差异。
解决方案
方法1:将列表转换为以ID为键的字典(推荐)
DeepDiff对比字典时会直接使用键作为路径的一部分,因此把原列表转成以id为键的字典,就能让差异路径直接显示ID值,无需额外处理。
from deepdiff import DeepDiff users1 = [{'id': 1, 'name': 'John', 'age': 30}, {'id': 2, 'name': 'Jane', 'age': 25}] users2 = [{'id': 1, 'name': 'John', 'age': 20}, {'id': 2, 'name': 'Bob', 'age': 35}] # 转换为以id为键的字典 users1_dict = {user['id']: user for user in users1} users2_dict = {user['id']: user for user in users2} diff = DeepDiff(users1_dict, users2_dict) print(diff)
输出结果(路径中的数字即为ID):
{'values_changed': {"root[1]['age']": {'new_value': 20, 'old_value': 30}, "root[2]['name']": {'new_value': 'Bob', 'old_value': 'Jane'}, "root[2]['age']": {'new_value': 35, 'old_value': 25}}}
方法2:修改DeepDiff的结果,替换索引为ID
如果必须保留原列表结构,可以遍历DeepDiff的结果,将路径中的索引替换为对应的ID值,还可进一步按ID分组展示。
替换路径中的索引为ID
from deepdiff import DeepDiff import re users1 = [{'id': 1, 'name': 'John', 'age': 30}, {'id': 2, 'name': 'Jane', 'age': 25}] users2 = [{'id': 1, 'name': 'John', 'age': 20}, {'id': 2, 'name': 'Bob', 'age': 35}] diff = DeepDiff(users1, users2) # 创建索引与ID的映射 index_to_id = {i: user['id'] for i, user in enumerate(users1)} # 替换values_changed中的路径 if 'values_changed' in diff: updated_changes = {} for path, change_info in diff['values_changed'].items(): # 提取路径中的索引 match = re.search(r'root\[(\d+)\]', path) if match: index = int(match.group(1)) target_id = index_to_id.get(index, index) # 替换索引为ID new_path = path.replace(f'root[{index}]', f'root[{target_id}]') updated_changes[new_path] = change_info diff['values_changed'] = updated_changes print(diff)
按ID分组展示差异
如果需要将同一ID的所有差异归类在一起,可进一步处理:
# 基于上面的updated_changes生成按ID分组的结果 grouped_diff = {'values_changed': {}} for path, change_info in updated_changes.items(): match = re.search(r'root\[(\d+)\]', path) if match: target_id = int(match.group(1)) if target_id not in grouped_diff['values_changed']: grouped_diff['values_changed'][target_id] = {} grouped_diff['values_changed'][target_id][path] = change_info print(grouped_diff)
输出结果:
{'values_changed': {1: {"root[1]['age']": {'new_value': 20, 'old_value': 30}}, 2: {"root[2]['name']": {'new_value': 'Bob', 'old_value': 'Jane'}, "root[2]['age']": {'new_value': 35, 'old_value': 25}}}}
内容的提问来源于stack exchange,提问作者Sanjay Kumar
相关产品推荐
相关产品推荐

