Per i seguenti due dict 'dictWithListsInValue' e 'reorderedDictWithReorderedListsInValue' che sono semplicemente versioni riordinate l'una dell'altra
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
mi ha dato un risultato sbagliato cioè falso.
Quindi ho creato il mio Cutstom ObjectComparator in questo modo:
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
che mi ha dato l'output previsto corretto!
La logica è piuttosto semplice:
Se gli oggetti sono di tipo "elenco", confronta ogni elemento del primo elenco con gli elementi del secondo elenco finché non vengono trovati, e se l'elemento non viene trovato dopo aver esaminato il secondo elenco, "trovato" sarebbe = falso. viene restituito il valore "trovato"
Altrimenti se gli oggetti da confrontare sono di tipo 'dict' allora confronta i valori presenti per tutte le rispettive chiavi in entrambi gli oggetti. (Viene eseguito il confronto ricorsivo)
Altrimenti chiama semplicemente obj1 == obj2. Di default funziona bene per l'oggetto di stringhe e numeri e per quelli eq () è definito in modo appropriato.
(Si noti che l'algoritmo può essere ulteriormente migliorato rimuovendo gli elementi trovati in object2, in modo che l'elemento successivo di object1 non si paragonerebbe con gli elementi già trovati in object2)