比较动态字典的无序列表



是,如果是这样,是否可以将无序列表或字典与动态键和值的相等性进行比较?

dict_list_1 = [ {'a': 'b'}, {'c': 'd'} ] 
dict_list_2 = [ {'c': 'd'}, {'a': 'b'} ]
dict_list_3 = [ {'c': 'd'}, {'d': 'c'} ]

其中dict_list_1dict_list_2应被视为相等,dict_list_3不应等于其他 2 个中的任何一个

字典的键(和值)是动态的,因此排序变得有点困难

比较 2 个字典相等的当前代码:

for a in dict_1.keys():
try:
if dict_1[a] != dict_2[a]:
return False
# recursive in case of dict within dict
if not equal_dict_values(dict_1[a], dict_2[a]):
return False
except KeyError:
return False
return True

但我不太确定如何处理无序列词问题。

这是一个通常应该有效的解决方案,即使列表具有同一字典的倍数,并且当一个列表中的字典可以具有公共键时也是如此。这个想法是将字典转换为规范的、可哈希的形式,然后使用Counter将它们作为袋子(可以包含多个的集合)进行比较。

它确实假定字典键是可比较的,并且字典值是可哈希的,因此如果您的字典具有不可比较的键或不可哈希值,它将不起作用。

from collections import Counter
def dict_to_canonical_hashable(d):
return tuple(sorted(d.items()))
def unordered_lists_equal(a, b):
canonical_a = Counter(map(dict_to_canonical_hashable, a))
canonical_b = Counter(map(dict_to_canonical_hashable, b))
return canonical_a == canonical_b

测试:

>>> unordered_lists_equal(dict_list_1, dict_list_2)
True
>>> unordered_lists_equal(dict_list_1, dict_list_3)
False
>>> unordered_lists_equal(dict_list_2, dict_list_3)
False
>>> unordered_lists_equal([{1: 2, 3: 4}, {5: 6}], [{1: 2}, {3: 4, 5: 6}])
False
>>> unordered_lists_equal([{1: 2}, {1: 3}], [{1: 3}, {1: 2}])
True
>>> unordered_lists_equal([{1: 2}, {1: 2}], [{1: 2}])
False
>>> unordered_lists_equal([{1: 2}, {1: 2}], [{1: 2}, {1: 2}])
True