2014-01-29 3 views
7

У меня есть N словарей, которые содержат одни и те же ключи со значениями, которые являются целыми числами. Я хочу объединить их в один словарь на основе максимального значения. В настоящее время у меня есть что-то вроде этого:Объединить несколько словарей условно

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 

Есть ли более (или более «вещий») способ сделать это?

ответ

7

Используйте collection.Counter() objects вместо этого, они поддерживают 'слияние' рассчитывает изначально:

from collections import Counter 

max_dict = Counter() 
for d in original_dict_list: 
    max_dict |= Counter(d) 

или даже:

from collections import Counter 
from operator import or_ 

max_dict = reduce(or_, map(Counter, original_dict_list)) 

Counter объекты мульти-наборы (также называемые 'мешки' иногда). Оператор | выполняет объединение на двух счетчиках, сохраняя максимальное количество для заданного ключа.

A Counter также является прямым подклассом dict, поэтому вы можете (в основном) относиться к нему как к любому другому словарю.

Демо:

>>> 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}) 
2

Если предположить, что не все словари содержат все ключи:

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} 
+1

В данном конкретном случае, вы можете использовать 'х [K]' вместо 'x.get (k, -1) ', потому что словари используют одни и те же ключи. Если бы они этого не сделали, я бы предложил заменить ваше внутреннее понимание списка на '[x [k] для x в original_dict_list, если k in x]' – Kevin

0
max_dict = { k:max([v]+[ _dict[k] for _dict in original_dict_list[1:] ]) 
      for k,v in original_dict_list[0].items() } 
Смежные вопросы