I'm trying to build some efficient code that can tell if one dict is a subset of another. Both dicts have string keys and int values. For dict1 to be considered a subset, it can not contain any unique keys and all values must be less than or equal to the equivalent key's value in dict2.
This almost worked:
test_dict.items() <= test_dict2.items()
until I tested it here:
test_dict = {
'a':1,
'c':2
}
test_dict2 = {
'a':1,
'b':2,
'c':3
}
test_dict.items() <= test_dict2.items()
False
I did get something working, but I dont know how efficient it really is
def test(request_totals, mongo_totals, max_limit=100):
outdated = dict()
sharedKeys = set(request_totals.keys()).intersection(mongo_totals.keys())
unsharedKeys = set(request_totals) - set(mongo_totals)
# Verifies MongoDB contains no unique collections
if set(mongo_totals) - set(request_totals) != set():
raise AttributeError(f'''mongo_totals does not appear to be a subset of request_totals.
Found: {set(mongo_totals) - set(request_totals)}''')
# Updates outdated dict with outdated key-value pairs representing MongoDB collections
for key in sharedKeys:
if request_totals[key] > mongo_totals[key]:
outdated.update({key : range(mongo_totals[key], request_totals[key])})
elif request_totals[key] < mongo_totals[key]:
raise AttributeError(
f'mongo_total for {key}: {mongo_totals[key]} exceeds request_totals for {key}: {request_totals[key]}')
return outdated
test(request_totals, mongo_totals)
It seems like a lot to do my comparison before creating an object that manages updates. Is there a better way to do this?
CodePudding user response:
You could try the collections Counter - it's very efficient and clear. Note - it's a new feature available in Python 3.10.
It's dict subclass for counting hashable objects
from collections import Counter
cd1 = Counter(test_dict)
cd2 = Counter(test_dict2)
print(cd1 <= cd2)
# True
#
# another example:
cd3 = Counter({'a': 2, 'b': 2, 'c': 3})
print(cd3 <= cd2)
#False
print(cd2 <= cd3)
#True
CodePudding user response:
all(test_dict2.get(k, v-1) >= v
for k, v in test_dict.items())