For the next two dictations, 'dictWithListsInValue' and 'reorderedDictWithReorderedListsInValue', which are simply reordered versions of each other
dictObj = {"foo": "bar", "john": "doe"} reorderedDictObj = {"john": "doe", "foo": "bar"} dictObj2 = {"abc": "def"} dictWithListsInValue = {'A': [{'X': [dictObj2, dictObj]}, {'Y': 2}], 'B': dictObj2} reorderedDictWithReorderedListsInValue = {'B': dictObj2, 'A': [{'Y': 2}, {'X': [reorderedDictObj, dictObj2]}]} a = {"L": "M", "N": dictWithListsInValue} b = {"L": "M", "N": reorderedDictWithReorderedListsInValue} print(sorted(a.items()) == sorted(b.items())) # gives false
gave me the wrong result i.e. false.
So I created my own ObjectComparator, like this:
def my_list_cmp(list1, list2): if (list1.__len__() != list2.__len__()): return False for l in list1: found = False for m in list2: res = my_obj_cmp(l, m) if (res): found = True break if (not found): return False return True def my_obj_cmp(obj1, obj2): if isinstance(obj1, list): if (not isinstance(obj2, list)): return False return my_list_cmp(obj1, obj2) elif (isinstance(obj1, dict)): if (not isinstance(obj2, dict)): return False exp = set(obj2.keys()) == set(obj1.keys()) if (not exp):
which gave me the correct expected result!
The logic is pretty simple:
If the objects are of the type “list”, then each element of the first list is compared with the elements of the second list until it is found, and if the element is not found after passing through the second list, then “found” will be false. 'found' value is returned
Otherwise, if the objects being compared are of type 'dict', compare the values present for all the corresponding keys in both objects. (A recursive comparison is performed)
Just call obj1 == obj2. By default, it works fine for an object of strings and numbers, and for them eq () is defined accordingly.
(Note that the algorithm can be further improved by deleting elements found in object2 so that the next element of object1 does not compare with elements already found in object2)