用数组检查深层嵌套的字典中几乎等于(请阅读描述)

check almost equals in deeply nested dicts with arrays (please read the desc)

假设我有两个嵌套的字典,里面有字典数组,我想检查值是否足够接近。 == 不起作用,因为它不检查数组值
扩展 ApproxMapping class 也不起作用

dict1 = {
'a': 1, 
'b': [
      {'c': [{'d': 32.069},{'e': 32.420}]}
     ]
}
dict2 = {
'a': 1, 
'b': [
      {'c': [{'d': 32.070},{'e': 32.421}]}
     ]
}

我如何检查它们是否几乎相等,我是否可以重写 pytest.approx 方法来处理嵌套的字典和数组?

检查 deepdiff 库:

from deepdiff import DeepDiff

dict1 = {
'a': 1, 
'b': [
      {'c': [{'d': 32.069},{'e': 32.420}]}
     ]
}
dict2 = {
'a': 1, 
'b': [
      {'c': [{'d': 32.070},{'e': 32.421}]}
     ]
}

diff = DeepDiff(dict1, dict2, significant_digits=2)
print(diff) # {}

这里有一个纯粹的 Python 方法,如果你想要的话:

def assert_values_almost_equal(value1, value2, tolerance=1e-5):
    if isinstance(value1, dict):
        assert_dicts_almost_equal(value1, value2, tolerance=tolerance)
    elif isinstance(value1, list):
        assert_sequences_almost_equal(value1, value2, tolerance=tolerance)
    elif isinstance(value1, (int, float)):
        assert_numbers_almost_equal(value1, value2, tolerance=tolerance)
    else:
        assert value1 == value2, f'Value 1: {n1} != Value 2: {n2}'

def assert_dicts_almost_equal(d1, d2, tolerance=1e-5):
    for (k1, v1), (k2, v2) in zip(d1.items(), d2.items()):
        assert_values_almost_equal(k1, k2, tolerance=tolerance)
        assert_values_almost_equal(v1, v2, tolerance=tolerance)

def assert_sequences_almost_equal(s1, s2, tolerance=1e-5):
    for e1, e2 in zip(s1, s2):
        assert_values_almost_equal(e1, e2, tolerance=tolerance)

def assert_numbers_almost_equal(n1, n2, tolerance=1e-5):
    assert abs(n1 - n2) < tolerance, f'Number 1: {n1} != Number 2: {n2}'

请注意,如果您想测试 assert_values_almost_equal 中未涵盖的其他数据类型(例如 numpy 数组),您需要添加适当的函数以及相应的 isinstance 检查(如果需要,请使用 np.testing.assert_array_almost_equal 作为断言)。

测试:

dict1 = {
'a': 1, 
'b': [
      {'c': [{'d': 32.069},{'e': 32.420}]}
     ]
}
dict2 = {
'a': 1, 
'b': [
      {'c': [{'d': 32.070},{'e': 32.421}]}
     ]
}

# passes
assert_dicts_almost_equal(dict1, dict2, tolerance=0.1)

# AssertionError: Number 1: 32.069 != Number 2: 32.07
assert_dicts_almost_equal(dict1, dict2, tolerance=0.0001)