说,我有两个列表:
a = [1,2,3]
和b = [2,3,1]
如果我执行a == b
,它将返回False
,
如果我选中sorted(a) == sorted(b)
,它将返回True
。
现在,我有两个对象:
obj1 = {'a': 1, 'b': 2, 'c': [1, 2]}
和obj2 = {'b': 2, 'a': 1, 'c': [1, 2]}
obj1 == obj2
为True,与键的顺序无关。
但是如果obj2 = {'b': 2, 'a': 1, 'c': [2, 1]}
我如何测试平等性?显然,obj1 == obj2
返回False。 sorted(obj1)
将具有['a', 'b', 'c']
,因此sorted(obj1) == sorted(obj2)
是一种浪费检查。
我可能应该重写该对象的相等方法,或者使用一些库。是,有什么方法可以编写用于深度平等的惯用python代码?
答案 0 :(得分:6)
sort
字典中的每个元素是否为list
类型,然后进行比较
>>> def sorted_element_dict(d):
... return {k:sorted(v) if isinstance(v, list) else v for k,v in d.items()}
...
>>> sorted_element_dict(obj1) == sorted_element_dict(obj2)
True
答案 1 :(得分:1)
如果您只对相等性检查感兴趣,请考虑使用all
。您可以将自定义比较器应用于所有字典值:
def check_equal(d1, d2):
if d1.keys() != d2.keys():
return False
return all(sorted(v) == sorted(d2[k]) if isinstance(v, list) else v == d2[k] for k, v in d1.items())
一种更优雅的方法可能是将比较器分解为一个单独的函数,并检查更一般的内容,例如collections.abc.Sequence
:
def check_equal(d1, d2):
if d1.keys() != d2.keys():
return False
def cmp(v1, v2):
if isinstance(v1, Sequence) and isinstance(v2, sequence):
return sorted(v1) == sorted(v2)
return v1 == v2
return all(cmp(v, d2[k]) for k, v in d1.items())
这具有不存储所有中间分类产品的优势。另一方面,如果您需要经常进行比较,则最好在使用常规==
之前先对字典进行转换:
def normalize(d):
for k, v in d.items():
if isinstance(v, Sequence):
d[k] = sorted(v)
请注意,我在这里使用循环而不是理解。这样,您的字典就可以进行原位转换,而不是分配整个新的哈希表。