当值的大小写无关紧要时,如何比较字典?



我有两个字典d1d2:

>>> d1 = {'name':'John Smith', 'age':36}
>>> d2 = {'name':'john smith', 'age':36}

我想确保,两个字典是相同的,但我不关心name值的情况。此外,我需要避免修改字典。

我可以通过像这样复制目录来解决这个问题:
>>> d1_lc = d1.copy()
>>> d2_lc = d2.copy()
>>>
>>> d1_lc['name'] = d1['name'].casefold()
>>> d2_lc['name'] = d2['name'].casefold()
>>>
>>> if d1_lc == d2_lc:
...     do_something_with_d1(d1)
...

也许有更好的方法?

使用生成器表达式检查每个值:

all(d1[k] == d2[k] if k != "name" else d1[k].lower() == d2[k].lower() for k in d1)
# True

必要时也可以添加set(d1.keys()) == set(d2.keys())

以下内容如何:

d1 = {'name':'John Smith', 'age':36}
d2 = {'name':'john smith', 'age':36}
def regularize(d):
return {k: (v.casefold() if isinstance(v, str) else v) for k, v in d.items()}
if regularize(d1) == regularize(d2):
print('hello!')

只将字符串值转换为小写。

更新:如果只有键'name'需要折叠,那么:

d1 = {'name':'John Smith', 'age':36}
d2 = {'name':'john smith', 'age':36}
def regularize(d):
return {k: (v.casefold() if k == 'name' else v) for k, v in d.items()}
if regularize(d1) == regularize(d2):
print('hello!')

我个人比较喜欢使用数据类的解决方案。

from dataclasses import dataclass
from functools import cached_property

@dataclass(frozen=True)
class Person:
name: str
age: int
def __eq__(self, other):
"""Compare with a case-insensitive match on the `name` field."""
if not isinstance(other, Person):
return False
return self.name_to_compare == other.name_to_compare
@cached_property
def name_to_compare(self):
return self.name.casefold()

测试代码:

if __name__ == '__main__':
d1 = {'name': 'John Smith', 'age': 36}
d2 = {'name': 'john smith', 'age': 36}
p1 = Person(**d1)
p2 = Person(**d2)
if p1 == p2:
print('Hooray!')
# access rest of attributes on class object instead of dict
# print('Person 1 name:', p1.name)