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

siv*_*iva 42 python merge dictionary compare

如果我有2个dicts如下:

d1 = {('unit1','test1'):2,('unit1','test2'):4}
d2 = {('unit1','test1'):2,('unit1','test2'):''}
Run Code Online (Sandbox Code Playgroud)

为了"合并"它们:

z = dict(d1.items() + d2.items())
z = {('unit1','test1'):2,('unit1','test2'):''}
Run Code Online (Sandbox Code Playgroud)

工作良好.另外要做什么,如果我想比较两个词典的每个值,如果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.
Run Code Online (Sandbox Code Playgroud)

请帮忙建议.

谢谢.

phi*_*hag 38

只需切换订单:

z = dict(d2.items() + d1.items())
Run Code Online (Sandbox Code Playgroud)

顺便说一句,您可能也对可能更快的update方法感兴趣.

在Python 3中,您必须首先将视图对象强制转换为列表:

z = dict(list(d2.items()) + list(d1.items())) 
Run Code Online (Sandbox Code Playgroud)

如果您想要特殊情况下的空字符串,可以执行以下操作:

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
Run Code Online (Sandbox Code Playgroud)


Mar*_*nen 27

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}
Run Code Online (Sandbox Code Playgroud)

  • ...这将改变输入`d2`.为什么不`dr = {}; dr.update(D1); dr.update((k,v)for(k,v)in d2.items()if v)`? (2认同)

Shm*_*ikA 9

Python 3.5+ 文字字典

\n

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

\n

Pythonic 和更快的字典解包方法:

\n
d1 = {\'a\':1, \'b\':1}\nd2 = {\'a\':2, \'c\':2}\nmerged = {**d1, **d2}  # priority from right to left\nprint(merged)\n\n{\'a\': 2, \'b\': 1, \'c\': 2}\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n
d1 = {i: 1 for i in range(1000000)}\nd2 = {i: 2 for i in range(2000000)}\n\n%timeit dict(list(d1.items()) + list(d2.items())) \n402 ms \xc2\xb1 33.3 ms per loop (mean \xc2\xb1 std. dev. of 7 runs, 1 loop each)\n\n%timeit {**d1, **d2}\n144 ms \xc2\xb1 1.12 ms per loop (mean \xc2\xb1 std. dev. of 7 runs, 10 loops each)\n
Run Code Online (Sandbox Code Playgroud)\n

更多关于PEP448的内容的内容:

\n
\n

字典中的键保持从右到左的优先顺序,因此 {**{\'a\': 1}, \'a\': 2, **{\'a\': 3}}计算结果为 {\'a\': 3}。拆包的数量或位置没有限制。

\n
\n

仅合并非零值

\n

为此,我们可以创建一个没有空值的字典,然后以这种方式将它们合并在一起:

\n
d1 = {\'a\':1, \'b\':1, \'c\': \'\', \'d\': \'\'}\nd2 = {\'a\':2, \'c\':2, \'d\': \'\'}\nmerged_non_zero = {\n    k: (d1.get(k) or d2.get(k))\n    for k in set(d1) | set(d2)\n}\nprint(merged_non_zero)\n
Run Code Online (Sandbox Code Playgroud)\n

输出:

\n
{\'a\': 1, \'b\': 1, \'c\': 2, \'d\': \'\'}\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  • a-> 更喜欢 d1 中的第一个值,因为 d1 和 d2 上都存在“a”
  • \n
  • b-> 仅存在于 d1 上
  • \n
  • c-> d2 上非零
  • \n
  • d-> 两者都为空字符串
  • \n
\n

解释

\n

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

\n

如果d1具有该值及其非零值(即bool(val) is True),则它将使用d1[k]value ,否则它将采用d2[k]

\n

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

\n


Ron*_*ian 6

为了增加d2键/值从d1不存在在d2没有覆盖任何现有键/值d2

temp = d2.copy()
d2.update(d1)
d2.update(temp)
Run Code Online (Sandbox Code Playgroud)


war*_*iuc 5

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

  • ...会更改`d2'的内容,这可能不是OP想要的。至少,`dict(d1.items()+ d2.items())`保持输入不变。 (8认同)

aon*_*152 5

这是一个就地解决方案(它修改了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
Run Code Online (Sandbox Code Playgroud)

这是另一个就地解决方案,它不太优雅,但可能会更有效,并且不会修改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]
Run Code Online (Sandbox Code Playgroud)