Reputation: 720
I have N dictionaries that contain the same keys, with values that are integers. I want to merge these into a single dictionary based on the maximum value. Currently I have something like this:
max_dict = {}
for dict in original_dict_list:
for key, val in dict.iteritems():
if key not in max_dict or max_dict[key] < val:
max_dict[key] = val
Is there a better (or more "pythonic") way of doing this?
Upvotes: 7
Views: 965
Reputation: 98088
Assuming not all dictionaries contain all keys:
keys = set(k for x in original_dict_list for k in x)
max_dict = {k:max([x[k] for x in original_dict_list if k in x]) for k in keys}
Upvotes: 2
Reputation: 4142
max_dict = { k:max([v]+[ _dict[k] for _dict in original_dict_list[1:] ])
for k,v in original_dict_list[0].items() }
Upvotes: 0
Reputation: 1123700
Use collection.Counter()
objects instead, they support 'merging' counts natively:
from collections import Counter
max_dict = Counter()
for d in original_dict_list:
max_dict |= Counter(d)
or even:
from collections import Counter
from operator import or_
max_dict = reduce(or_, map(Counter, original_dict_list))
Counter
objects are multi-sets (also called 'bags' sometimes). The |
operator performs a union on two counters, storing the maximum count for a given key.
A Counter
is also a straight subclass of dict
, so you can (mostly) treat it like any other dictionary.
Demo:
>>> from collections import Counter
>>> from operator import or_
>>> original_dict_list = [{'foo': 3, 'bar': 10}, {'foo': 42, 'spam': 20}, {'bar': 5, 'ham': 10}]
>>> reduce(or_, map(Counter, original_dict_list))
Counter({'foo': 42, 'spam': 20, 'bar': 10, 'ham': 10})
Upvotes: 7