Python:如果存在值,则通过更新而不是覆盖来进行字典合并

时间:2011-06-15 07:29:57

标签: python dictionary merge compare

如果我有以下两个词:

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'):''}

工作正常。 另外要做什么,如果我想比较两个词典的每个值,只有当d1中的值为空/无/'时才将d2更新为d1?

[编辑] 问题:当将d2更新为d1时,当存在相同的键时,我只想保持数值(来自d1或d2)而不是空值。如果两个值都为空,那么保持空值没有问题。如果两者都有值,则应保留d1值。 :)(lota if-else ..我会在此期间尝试自己)

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.

请帮忙建议。

感谢。

8 个答案:

答案 0 :(得分:36)

只需切换订单:

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

答案 1 :(得分:26)

Python 2.7。使用d1键/值对更新d2,但仅当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}

答案 2 :(得分:4)

d2.update(d1)代替dict(d2.items() + d1.items())

答案 3 :(得分:4)

这是一个就地解决方案(它修改了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 :(得分:3)

要添加d2 d1d2个{/ 1}}中不存在的{/ 1}}值,而不覆盖d2中的任何现有键/值:

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

答案 5 :(得分:3)

仅合并非零值

要做到这一点,我们可以创建一个没有空值的字典,然后通过以下方式将它们合并在一起:

foreach ($array as $value) {
    foreach ($deletes as $delete) {
        if ($value == $delete) {
            continue 2;            // goto next value in outer loop without pushing
        }
        if ($value > $delete) {
            --$value;              // decrement value
        }
    }
    $result[] = $value;            // push adjusted value into result array
}
var_export($result);

输出:

d1 = {'a':1, 'b':1, 'c': '', 'd': ''}
d2 = {'a':2, 'c':2, 'd': ''}
merged_non_zero = {
    k: (d1.get(k) or d2.get(k))
    for k in set(d1) | set(d2)
}
print(merged_non_zero)
  • {'a': 1, 'b': 1, 'c': 2, 'd': ''} ->首选d1中的第一个值,因为d1和d2上都存在'a'
  • a->仅存在于d1
  • b->在d2上非零
  • c->两者均为空字符串

说明

上面的代码将使用dict理解来创建字典。

如果d具有该值及其非零值(即d1),它将使用bool(val) is True值,否则将使用d1[k]。 / p>

请注意,我们还合并了两个字典的所有键,因为它们可能不具有使用set union-d2[k]完全相同的键。

Python 3.5+文字字典

除非使用过时的python版本,否则最好使用它。

字典解包的Python快捷方式:

set(d1) | set(d2)

它比d1 = {'a':1, 'b':1} d2 = {'a':2, 'c':2} merged = {**d1, **d2} # priority from right to left print(merged) {'a': 2, 'b': 1, 'c': 2} 替代方案更简单,也更快:

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

有关PEP448的更多信息:

字典中的键仍按从右到左的优先顺序排列,因此{** {'a':1},'a':2,2,** {'a':3}}的计算结果为{ 'a':3}。开箱数量或位置没有限制。

答案 6 :(得分:2)

如果您拥有相同大小和键的字典,则可以使用以下代码:

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

答案 7 :(得分:1)

如果您想忽略空格以便合并:

a = {"a": 1, "b": 2, "c": ""}
b = {"a": "", "b": 4, "c": 5}
c = {"a": "aaa", "b": ""}
d = {"a": "", "w": ""}

导致:{'a': 'aaa', 'b': 4, 'c': 5, 'w': ''}

您可以使用这两个功能:

def merge_two_dicts(a, b, path=None):
    "merges b into a"
    if path is None:
        path = []
    for key in b:
        if key in a:
            if isinstance(a[key], dict) and isinstance(b[key], dict):
                merge_two_dicts(a[key], b[key], path + [str(key)])
            elif a[key] == b[key]:
                pass  # same leaf value
            else:
                if a[key] and not b[key]:
                    a[key] = a[key]
                else:
                    a[key] = b[key]
        else:
            a[key] = b[key]
    return a


def merge_multiple_dicts(*a):
    output = a[0]
    if len(a) >= 2:
        for n in range(len(a) - 1):
            output = merge_two_dicts(output, a[n + 1])

    return output

所以你可以使用 merge_multiple_dicts(a,b,c,d)