a_standard = {
'section1': {
'category1': 1,
'category2': 2
},
'section2': {
'category1': 1,
'category2': 2
}
}
a_new = {
'section1': {
'category1': 1,
'category2': 2
},
'section2': {
'category1': 1,
'category2': 3
}
}
我想找到 a_standard
和 a_new
之间的区别,它在 a_new[section2][category2]
中的区别是 2
和 3
我应该将每个转换为一个集合,然后进行差分还是循环比较字典?
最佳答案
有一个图书馆叫deepdiff有很多选项,但我发现它有点不直观。
这是我在单元测试期间经常用来计算差异的递归函数。这超出了问题的范围,因为我也处理了嵌套列表的情况。我希望你会发现它有用。
函数定义:
from copy import deepcopy
def deep_diff(x, y, parent_key=None, exclude_keys=[], epsilon_keys=[]):
"""
Take the deep diff of JSON-like dictionaries
No warranties when keys, or values are None
"""
EPSILON = 0.5
rho = 1 - EPSILON
if x == y:
return None
if parent_key in epsilon_keys:
xfl, yfl = float_or_None(x), float_or_None(y)
if xfl and yfl and xfl * yfl >= 0 and rho * xfl <= yfl and rho * yfl <= xfl:
return None
if type(x) != type(y) or type(x) not in [list, dict]:
return x, y
if type(x) == dict:
d = {}
for k in x.keys() ^ y.keys():
if k in exclude_keys:
continue
if k in x:
d[k] = (deepcopy(x[k]), None)
else:
d[k] = (None, deepcopy(y[k]))
for k in x.keys() & y.keys():
if k in exclude_keys:
continue
next_d = deep_diff(x[k], y[k], parent_key=k, exclude_keys=exclude_keys, epsilon_keys=epsilon_keys)
if next_d is None:
continue
d[k] = next_d
return d if d else None
# assume a list:
d = [None] * max(len(x), len(y))
flipped = False
if len(x) > len(y):
flipped = True
x, y = y, x
for i, x_val in enumerate(x):
d[i] = deep_diff(y[i], x_val, parent_key=i, exclude_keys=exclude_keys, epsilon_keys=epsilon_keys) if flipped else deep_diff(x_val, y[i], parent_key=i, exclude_keys=exclude_keys, epsilon_keys=epsilon_keys)
for i in range(len(x), len(y)):
d[i] = (y[i], None) if flipped else (None, y[i])
return None if all(map(lambda x: x is None, d)) else d
# We need this helper function as well:
def float_or_None(x):
try:
return float(x)
except ValueError:
return None
用法:
>>> deep_diff(a_standard, a_new)
{'section2': {'category2': (2, 3)}}
我认为输出比其他答案更直观一些。
在单元测试中我会这样:
import json
diff = deep_diff(expected_out, out, exclude_keys=["flickery1", "flickery2"])
assert diff is None, json.dumps(diff, indent=2)
关于python - 如何比较嵌套的字典,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48652762/