Python allows dictionaries to be compared with ==
import copy
child = {'name': 'child'}
parent_1 = {'name': 'parent', 'child': child}
parent_2 = copy.deepcopy(parent_1)
print(parent_1 == parent_2)
Prints True
, as you would expect it to.
Python also allows dictionaries to reference each other circularly.
child = {'name': 'child'}
parent_1 = {'name': 'parent', 'child': child}
child['parent'] = parent_1 # Create the circular reference
However, trying to use the ==
operator on dictionaries with circular references raises an error.
parent_2 = copy.deepcopy(parent_1)
print(parent_1 == parent_2)
Returns
C:\Python34\python.exe -i C:/Users/anon/.PyCharm40/config/scratches/scratch_5
Traceback (most recent call last):
File "C:/Users/anon/.PyCharm40/config/scratches/scratch_5", line 11, in <module>
print(parent_1 == parent_2)
RuntimeError: maximum recursion depth exceeded in comparison
How can I check two dictionaries with circular references for equality?
You need to define what you mean by equal. Normally "equal" for dictionaries means 'all the key/value pairs are the "equal"'. If a dictionary has a reference to itself, this definition of equal may lead to a recursive definition, i.e. a == b
iff a == b
.
Take this simple example:
a = {}; a['item'] = a
b = {}; b['item'] = b
Are a
and b
equal? In order to know that, you need to first know if a
and b
are equal ...
You could create a special equal
that looks something like this:
def equal(a, b, special=[]):
if not isinstance(a, dict) or not isinstance(b, dict):
return a == b
special = special + [a, b]
set_keys = set(a.keys())
if set_keys != set(b.keys()):
return False
for key in set_keys:
if any(a[key] is i for i in special):
continue
elif any(b[key] is i for i in special):
continue
elif not equal(a[key], b[key], special):
return False
return True