Reputation: 1177
I have two dictionaries d1
and d2
:
>>> d1 = {'name':'John Smith', 'age':36}
>>> d2 = {'name':'john smith', 'age':36}
I want to make sure, that two dictionaries are identical, but I don't care about the name
value case. In addition, I need to avoid modifying the dictionaries.
I could solve it by copying directories like this:
>>> 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)
...
Perhaps there is a better way?
Upvotes: 0
Views: 101
Reputation: 32548
Use a generator expression to check each value:
all(d1[k] == d2[k] if k != "name" else d1[k].lower() == d2[k].lower() for k in d1)
# True
You can also add set(d1.keys()) == set(d2.keys())
if necessary.
Upvotes: 3
Reputation: 11612
Here's a solution using dataclasses which I personally prefer.
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()
Code for testing:
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)
Upvotes: 1
Reputation: 13939
How about the following:
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!')
This converts only the string values into lower case.
Update: If only the key 'name'
needs to be casefolded, then:
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!')
Upvotes: 3