Python: словарь объединяется путем обновления, но не перезаписи, если значение существует - PullRequest
39 голосов
/ 15 июня 2011

Если у меня есть 2 дикта следующим образом:

d1 = {('unit1','test1'):2,('unit1','test2'):4}
d2 = {('unit1','test1'):2,('unit1','test2'):''}

Чтобы «объединить» их:

z = dict(d1.items() + d2.items())
z = {('unit1','test1'):2,('unit1','test2'):''}

Работает нормально. Кроме того, что делать, если я хочу сравнить каждое значение двух словарей и обновить d2 до d1, только если значения в d1 пусты / Нет / ''?

[EDIT] Вопрос: При обновлении d2 до d1, когда существует тот же ключ, я хотел бы сохранить только числовое значение (либо из d1, либо из d2) вместо пустого значения. Если оба значения являются пустыми, то нет проблем с поддержанием пустого значения. Если оба имеют значения, то значение d1 должно остаться. :) (Лота, если-еще .. я бы попробовал себя тем временем)

т.е.

d1 = {('unit1','test1'):2,('unit1','test2'):8,('unit1','test3'):''}
d2 = {('unit1','test1'):2,('unit1','test2'):'',('unit1','test3'):''}

#compare & update codes

z = {('unit1','test1'):2,('unit1','test2'):8, ('unit1','test2'):''} # 8 not overwritten by empty.

пожалуйста, помогите предложить.

Спасибо.

Ответы [ 6 ]

36 голосов
/ 15 июня 2011

Просто переключите заказ:

z = dict(d2.items() + d1.items())

Кстати, вас также может заинтересовать потенциально более быстрый update метод.

В Python 3 вы должны сначала преобразовать объекты представления в списки:

z = dict(list(d2.items()) + list(d1.items())) 

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

def mergeDictsOverwriteEmpty(d1, d2):
    res = d2.copy()
    for k,v in d2.items():
        if k not in d1 or d1[k] == '':
            res[k] = v
    return res
26 голосов
/ 15 июня 2011

Python 2.7. Обновляет d2 парами ключ / значение d1, но только если значение d1 не равно None, '' (False):

>>> d1 = dict(a=1,b=None,c=2)
>>> d2 = dict(a=None,b=2,c=1)
>>> d2.update({k:v for k,v in d1.iteritems() if v})
>>> d2
{'a': 1, 'c': 2, 'b': 2}
4 голосов
/ 15 марта 2017

Вот решение на месте (оно изменяет d2):

# assumptions: d2 is a temporary dict that can be discarded
# d1 is a dict that must be modified in place
# the modification is adding keys from d2 into d1 that do not exist in d1.

def update_non_existing_inplace(original_dict, to_add):
    to_add.update(original_dict) # to_add now holds the "final result" (O(n))
    original_dict.clear() # erase original_dict in-place (O(1))
    original_dict.update(to_add) # original_dict now holds the "final result" (O(n))
    return

Вот еще одно решение на месте , которое менее элегантно, но потенциально болееэффективный, а также оставляя d2 неизменным :

# assumptions: d2 is can not be modified
# d1 is a dict that must be modified in place
# the modification is adding keys from d2 into d1 that do not exist in d1.

def update_non_existing_inplace(original_dict, to_add):
    for key in to_add.iterkeys():
        if key not in original_dict:
            original_dict[key] = to_add[key]
4 голосов
/ 15 июня 2011

d2.update(d1) вместо dict(d2.items() + d1.items())

3 голосов
/ 16 мая 2018

Чтобы добавить к d2 ключи / значения из d1, которые не существуют в d2, без перезаписи любых существующих ключей / значений в d2:

temp = d2.copy()
d2.update(d1)
d2.update(temp)
2 голосов
/ 15 июня 2011

Если у вас есть словари с одинаковым размером и клавишами, вы можете использовать следующий код:

dict((k,v if k in d2 and d2[k] in [None, ''] else d2[k]) for k,v in d1.iteritems())
...