2016-06-06 3 views
1

Есть ли лучше/вещий способ сделать следующее:Pythonic способ получить объединение словарей

У меня есть функция, которая сливает словарей:

def merge_dicts(a, *dict_args): 
    for dictionary in dict_args: 
     for k, v in dictionary.items(): 
      if k not in a: 
       a[k] = v 

    return a 

Вот пример работы:

a = {'A': 1, 'B': 2} 
b = {'B': 3, 'C': 4} 
c = merge_dicts(a, b) # {'A': 1, 'B': 2, 'C': 4} 

Я использую python2.7.

+0

Что такое ваше определение слияния? который B получает приоритет? –

+0

Если ключ уже существует в более раннем словаре, он не будет перезаписан одним и тем же ключом с другим значением. Другими словами, B от dict a получает приоритет. – Mico

ответ

2

Вы можете использовать update. Поскольку ранее dicts имеют приоритет необходимо обновить в обратном порядке, и обновление с a последним:

def merge_dicts(a, *dict_args): 
    d = {} 
    for dictionary in reversed(dict_args): 
     d.update(dictionary) 
    d.update(a) 
    return d 

Или как однострочник, используя itertools.chain:

from itertools import chain 

def merge_dicts(a, *dict_args): 
    # chain (key, value) items in order of increasing priority 
    return dict(chain.from_iterable(d.iteritems() for d in dict_args[::-1]+(a,))) 

> merge_dicts(a, b) 
{'A': 1, 'C': 4, 'B': 2} 

Если я могу добавить, почему не удалить a из сигнатуры функции в целом:

def merge_dicts(*dict_args): 
    return dict(chain.from_iterable(d.iteritems() for d in dict_args[::-1])) 
# If you provide 0 or 1 dict, 
# this will return an empty dict or the single dict (a copy thereof) itself 
+0

Вы можете использовать 'chain.from_iterable (...)'. Вместо 'chain (* ...)'. –

+0

@DanD. Я всегда задаюсь вопросом, какой из двух лучше/читаем. Я склонен идти с более коротким, к которому я привык. Есть ли неотъемлемое преимущество «chain.from_iterable»? ** Редактирование: ** Я думаю, для 'chain (* ...)' он должен создать «кортеж» из генератора. Обновлен мой ответ. – schwobaseggl

1

Вам не нужно, чтобы проверить наличие ключей в словарях, так как вы хотите сохранить тыс е первый ключ, который вы можете использовать Dict понимание, обернув по списку словарей назад:

{k: v for d in list_of_dict[::-1] for k, v in d.items()} 

Python заменит существование ключей с новыми, каждый раз, когда сталкиваются дубликат один, и так как вы перекручивание через список назад, он будет содержать первые ключи в вашем агрегированном словаре.

Основываясь на вашем примере:

>>> {k: v for d in l[::-1] for k, v in d.items()} 
{'A': 1, 'C': 4, 'B': 2} 
Смежные вопросы