Как объединить словари в Python?

d3 = dict(d1, **d2)

Я понимаю, что это слияние словаря. Но уникально ли это? Что, если d1 имеет тот же ключ, что и d2, но другое значение? Я бы хотел, чтобы d1 и d2 были объединены, но d1 имеет приоритет, если имеется дублированный ключ.

Ответ 1

Вы можете использовать метод .update(), если вам больше не нужен оригинальный d2:

Обновите словарь с помощью пар ключ/значение из другого, перезаписи существующих ключей. Верните None.

например:.

>>> d1 = {'a': 1, 'b': 2} 
>>> d2 = {'b': 1, 'c': 3}
>>> d2.update(d1)
>>> d2
{'a': 1, 'c': 3, 'b': 2}

Update:

Конечно, вы можете скопировать словарь сначала, чтобы создать новый объединенный. Это может потребоваться или не понадобиться. Если у вас есть составные объекты (объекты, которые содержат другие объекты, например списки или экземпляры классов) в вашем словаре, copy.deepcopy также следует учитывать.

Ответ 2

В Python2,

d1={'a':1,'b':2}
d2={'a':10,'c':3}

d1 переопределяет d2:

dict(d2,**d1)
# {'a': 1, 'c': 3, 'b': 2}

d2 переопределяет d1:

dict(d1,**d2)
# {'a': 10, 'c': 3, 'b': 2}

Это поведение не просто случайность реализации; в документации :

Если ключ указан как в позиционный аргумент и ключевое слово аргумент, значение, связанное с ключевое слово сохраняется в словарь.

Ответ 3

Если вы хотите, чтобы d1 имел приоритет в конфликтах, выполните следующие действия:

d3 = d2.copy()
d3.update(d1)

В противном случае, обратные d2 и d1.

Ответ 4

Мое решение - определить функцию слияния. Это не сложно и просто стоит одной линии. Здесь код в Python 3.

from functools import reduce
from operator import or_

def merge(*dicts):
    return { k: reduce(lambda d, x: x.get(k, d), dicts, None) for k in reduce(or_, map(lambda x: x.keys(), dicts), set()) }

Испытания

>>> d = {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
>>> d_letters = {0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f', 6: 'g', 7: 'h', 8: 'i', 9: 'j', 10: 'k', 11: 'l', 12: 'm', 13: 'n', 14: 'o', 15: 'p', 16: 'q', 17: 'r', 18: 's', 19: 't', 20: 'u', 21: 'v', 22: 'w', 23: 'x', 24: 'y', 25: 'z', 26: 'A', 27: 'B', 28: 'C', 29: 'D', 30: 'E', 31: 'F', 32: 'G', 33: 'H', 34: 'I', 35: 'J', 36: 'K', 37: 'L', 38: 'M', 39: 'N', 40: 'O', 41: 'P', 42: 'Q', 43: 'R', 44: 'S', 45: 'T', 46: 'U', 47: 'V', 48: 'W', 49: 'X', 50: 'Y', 51: 'Z'}
>>> merge(d, d_letters)
{0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f', 6: 'g', 7: 'h', 8: 'i', 9: 'j', 10: 'k', 11: 'l', 12: 'm', 13: 'n', 14: 'o', 15: 'p', 16: 'q', 17: 'r', 18: 's', 19: 't', 20: 'u', 21: 'v', 22: 'w', 23: 'x', 24: 'y', 25: 'z', 26: 'A', 27: 'B', 28: 'C', 29: 'D', 30: 'E', 31: 'F', 32: 'G', 33: 'H', 34: 'I', 35: 'J', 36: 'K', 37: 'L', 38: 'M', 39: 'N', 40: 'O', 41: 'P', 42: 'Q', 43: 'R', 44: 'S', 45: 'T', 46: 'U', 47: 'V', 48: 'W', 49: 'X', 50: 'Y', 51: 'Z'}
>>> merge(d_letters, d)
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 'f', 6: 'g', 7: 'h', 8: 'i', 9: 'j', 10: 'k', 11: 'l', 12: 'm', 13: 'n', 14: 'o', 15: 'p', 16: 'q', 17: 'r', 18: 's', 19: 't', 20: 'u', 21: 'v', 22: 'w', 23: 'x', 24: 'y', 25: 'z', 26: 'A', 27: 'B', 28: 'C', 29: 'D', 30: 'E', 31: 'F', 32: 'G', 33: 'H', 34: 'I', 35: 'J', 36: 'K', 37: 'L', 38: 'M', 39: 'N', 40: 'O', 41: 'P', 42: 'Q', 43: 'R', 44: 'S', 45: 'T', 46: 'U', 47: 'V', 48: 'W', 49: 'X', 50: 'Y', 51: 'Z'}
>>> merge(d)
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
>>> merge(d_letters)
{0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f', 6: 'g', 7: 'h', 8: 'i', 9: 'j', 10: 'k', 11: 'l', 12: 'm', 13: 'n', 14: 'o', 15: 'p', 16: 'q', 17: 'r', 18: 's', 19: 't', 20: 'u', 21: 'v', 22: 'w', 23: 'x', 24: 'y', 25: 'z', 26: 'A', 27: 'B', 28: 'C', 29: 'D', 30: 'E', 31: 'F', 32: 'G', 33: 'H', 34: 'I', 35: 'J', 36: 'K', 37: 'L', 38: 'M', 39: 'N', 40: 'O', 41: 'P', 42: 'Q', 43: 'R', 44: 'S', 45: 'T', 46: 'U', 47: 'V', 48: 'W', 49: 'X', 50: 'Y', 51: 'Z'}
>>> merge()
{}

Он работает для произвольного количества аргументов словаря. Если в этом словаре есть дубликаты ключей, выигрывает ключ из самого правого словаря в списке аргументов.

Ответ 6

Я считаю, что, как указано выше, использование d2.update(d1) является наилучшим подходом и что вы также можете скопировать d2, если он вам еще нужен.

Хотя я хочу отметить, что dict(d1, **d2) на самом деле является плохим способом объединить словари в целом, поскольку аргументы ключевого слова должны быть строками, поэтому он будет терпеть неудачу, если у вас есть dict, например:

{
  1: 'foo',
  2: 'bar'
}