I couldn't get Akavall's function to run so made my own. Is a little too simple but works for my purposes. Code to test that function is working written using pytest
from numbers import Number
from math import isclose
def dictsAlmostEqual(dict1, dict2, rel_tol=1e-8):
"""
If dictionary value is a number, then check that the numbers are almost equal, otherwise check if values are exactly equal
Note: does not currently try converting strings to digits and comparing them. Does not care about ordering of keys in dictionaries
Just returns true or false
"""
if len(dict1) != len(dict2):
return False
# Loop through each item in the first dict and compare it to the second dict
for key, item in dict1.items():
# If it is a nested dictionary, need to call the function again
if isinstance(item, dict):
# If the nested dictionaries are not almost equal, return False
if not dictsAlmostEqual(dict1[key], dict2[key], rel_tol=rel_tol):
return False
# If it's not a dictionary, then continue comparing
# Put in else statement or else the nested dictionary will get compared twice and
# On the second time will check for exactly equal and will fail
else:
# If the value is a number, check if they are approximately equal
if isinstance(item, Number):
# if not abs(dict1[key] - dict2[key]) <= rel_tol:
# https://stackoverflow.com/questions/5595425/what-is-the-best-way-to-compare-floats-for-almost-equality-in-python
if not isclose(dict1[key], dict2[key], rel_tol=rel_tol):
return False
else:
if not (dict1[key] == dict2[key]):
return False
return True
Validate function output using pytest
import pytest
import dictsAlmostEqual
def test_dictsAlmostEqual():
a = {}
b = {}
assert dictsAlmostEqual(a, b)
a = {"1": "a"}
b = {}
assert not dictsAlmostEqual(a, b)
a = {"1": "a"}
b = {"1": "a"}
assert dictsAlmostEqual(a, b)
a = {"1": "a"}
b = {"1": "b"}
assert not dictsAlmostEqual(a, b)
a = {"1": "1.23"}
b = {"1": "1.23"}
assert dictsAlmostEqual(a, b)
a = {"1": "1.234"}
b = {"1": "1.23"}
assert not dictsAlmostEqual(a, b)
a = {"1": 1.000000000000001, "2": "a"}
b = {"1": 1.000000000000002, "2": "a"}
assert not dictsAlmostEqual(a, b, rel_tol=1e-20)
assert dictsAlmostEqual(a, b, rel_tol=1e-8)
assert dictsAlmostEqual(a, b)
# Nested dicts
a = {"1": {"2": 1.000000000000001}}
b = {"1": {"2": 1.000000000000002}}
assert not dictsAlmostEqual(a, b, rel_tol=1e-20)
assert dictsAlmostEqual(a, b, rel_tol=1e-8)
assert dictsAlmostEqual(a, b)
a = {"1": {"2": 1.000000000000001, "3": "a"}, "2": "1.23"}
b = {"1": {"2": 1.000000000000002, "3": "a"}, "2": "1.23"}
assert not dictsAlmostEqual(a, b, rel_tol=1e-20)
assert dictsAlmostEqual(a, b, rel_tol=1e-8)
assert dictsAlmostEqual(a, b)