d3 = dict(d1, **d2)
Я так понимаю, это объединяет словарь. Но уникальна ли она? Что, если d1 имеет тот же ключ, что и d2, но другое значение? Я бы хотел, чтобы d1 и d2 были объединены, но d1 имеет приоритет, если есть повторяющийся ключ.
python
dictionary
TIMEX
источник
источник
**
передачей аргументов ключевого слова, если только все ключи неd2
являются строками. Если не все ключиd2
являются строками, это не удается в Python 3.2 и в альтернативных реализациях Python, таких как Jython, IronPython и PyPy. См., Например, mail.python.org/pipermail/python-dev/2010-April/099459.html .Ответы:
Вы можете использовать
.update()
метод, если вам больше не нужен оригиналd2
:Например:
>>> d1 = {'a': 1, 'b': 2} >>> d2 = {'b': 1, 'c': 3} >>> d2.update(d1) >>> d2 {'a': 1, 'c': 3, 'b': 2}
Обновить:
Конечно, вы можете сначала скопировать словарь, чтобы создать новый объединенный. Это может быть необходимо, а может и нет. Если у вас есть составные объекты (объекты, которые содержат другие объекты, такие как списки или экземпляры классов) в вашем словаре,
copy.deepcopy
также следует учитывать.источник
isinstance(int, object) is True
ноdeepcopy
это не кажется необходимым.В 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}
Такое поведение не просто случайность реализации; это гарантируется в документации :
источник
**
обозначением все ключи этого словаря должны быть строками. См. Ветку python-dev, начинающуюся с mail.python.org/pipermail/python-dev/2010-April/099427.html, чтобы узнать больше.d = dict(**d1, **d2)
работает, но @IoannisFilippidis ссылается на это в своем комментарии. Возможно, включение здесь фрагмента было бы более ясным, так что вот он.Если вы хотите
d1
иметь приоритет в конфликтах, сделайте:В противном случае поменяйте местами
d2
иd1
.источник
Мое решение - определить функцию слияния . Это не сложно и стоит всего одну строчку. Вот код на 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() {}
Он работает для произвольного количества словарных аргументов. Если бы в этом словаре были какие-либо повторяющиеся ключи, победит ключ из самого правого словаря в списке аргументов.
источник
.update
вызовом в нем (merged={}
за которым следуетfor d in dict: merged.update(d)
) будет короче, удобочитаемее и эффективнее.reduce
иlambda
, как насчетreturn reduce(lambda x, y: x.update(y) or x, dicts, {})
?У Трея Ханнера есть хорошая запись в блоге, в которой описаны несколько вариантов объединения нескольких словарей, включая (для python3.3 +) ChainMap и распаковку словарей .
источник
Начиная с
Python 3.9
, оператор|
создает новый словарь с объединенными ключами и значениями из двух словарей:# d1 = { 'a': 1, 'b': 2 } # d2 = { 'b': 1, 'c': 3 } d3 = d2 | d1 # d3: {'b': 2, 'c': 3, 'a': 1}
Этот:
Также обратите внимание на
|=
оператор, который изменяет d2 путем объединения d1 с приоритетом значений d1:# d1 = { 'a': 1, 'b': 2 } # d2 = { 'b': 1, 'c': 3 } d2 |= d1 # d2: {'b': 2, 'c': 3, 'a': 1}
источник
Я считаю, что, как указано выше, использование
d2.update(d1)
- лучший подход и что вы также можете скопироватьd2
сначала если вам все еще нужно.Хотя я хочу отметить, что
dict(d1, **d2)
на самом деле это плохой способ слияния словарей в целом, поскольку аргументы ключевых слов должны быть строками, поэтому он не удастся, если у вас естьdict
такие как:{ 1: 'foo', 2: 'bar' }
источник