Para los siguientes dos dicts 'dictWithListsInValue' y 'reorderedDictWithReorderedListsInValue', que son simplemente versiones reordenadas entre sí
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
me dio un resultado incorrecto, es decir, falso.
Así que creé mi propio ObjectComparator cutstom así:
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):
# print(obj1.keys(), obj2.keys())
return False
for k in obj1.keys():
val1 = obj1.get(k)
val2 = obj2.get(k)
if isinstance(val1, list):
if (not my_list_cmp(val1, val2)):
return False
elif isinstance(val1, dict):
if (not my_obj_cmp(val1, val2)):
return False
else:
if val2 != val1:
return False
else:
return obj1 == obj2
return True
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(my_obj_cmp(a, b)) # gives true
lo que me dio el resultado esperado correcto!
La lógica es bastante simple:
Si los objetos son del tipo 'lista', compare cada elemento de la primera lista con los elementos de la segunda lista hasta que los encuentre, y si el elemento no se encuentra después de pasar por la segunda lista, entonces 'encontrado' sería = falso. se devuelve el valor 'encontrado'
De lo contrario, si los objetos a comparar son de tipo 'dict', compare los valores presentes para todas las claves respectivas en ambos objetos. (Se realiza una comparación recursiva)
De lo contrario, simplemente llame a obj1 == obj2. De forma predeterminada, funciona bien para el objeto de cadenas y números y para esos eq () se define adecuadamente.
(Tenga en cuenta que el algoritmo se puede mejorar aún más eliminando los elementos que se encuentran en object2, de modo que el siguiente elemento de object1 no se compare con los elementos que ya se encuentran en el object2)