用数组检查深层嵌套的字典中几乎等于(请阅读描述)
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)
假设我有两个嵌套的字典,里面有字典数组,我想检查值是否足够接近。
== 不起作用,因为它不检查数组值
扩展 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)