用另一个字典更新一个字典,但只更新非空值。

13
从Python 文档中,我看到dict有一个update(...)方法,但似乎它不接受异常,我可能不想用新值更新旧字典的情况。例如,当值为None时。

这是我目前的做法:

for key in new_dict.keys():
  new_value = new_dict.get(key)
  if new_value: old_dict[key] = new_value

有没有更好的方法使用新字典更新旧字典。


1
你的代码还会丢弃 False0。你也可以使用 for k,v in new_dict.items(): 进行迭代。 - t-8ch
4个回答

18

您可以使用类似以下的代码:

old = {1: 'one', 2: 'two'}
new = {1: 'newone', 2: None, 3: 'new'}

old.update( (k,v) for k,v in new.items() if v is not None)

# {1: 'newone', 2: 'two', 3: 'new'}

1

更新:我认为我在回答错误的问题(请参见下面的评论),因为这显然不能回答所问的问题。如果有用的东西,我还是会留在这里的(除非有人明确表示最好删除它)。

Jon的答案的基础上,但使用set intersection此处建议:

在Python 3中:

old.update((k, new[k]) for k in old.keys() & new.keys())

在Python 2.7中:
old.update((k, new[k]) for k in old.viewkeys() & new.viewkeys())

在Python 2.7或3中,使用future包:
from future.utils import viewkeys
old.update((k, new[k]) for k in viewkeys(old) & viewkeys(new))

或者在Python 2或3中,通过创建新的集合而不使用future包:

old.update((k, new[k]) for k in set(old.keys()) & set(new.keys()))

1
实际上这看起来很好,但是update()已经只更新在new中存在的键。然而,它并没有回答值为None且跳过这些键的问题。 - Sunny Patel
1
@SunnyPatel 你说得对!事实上,现在我再看这个问题,我发现我的解决方案也无法更新old中不存在的键的值。实际上,我想我一定是在回答错误的问题:“如何(高效地)仅更新已经存在于old中的键的值?” 对于这个问题,这个解决方案中的时间表明,即使不必要,交集实际上可以有助于性能。(谢谢!) - teichert

0

如果要在Python 3.x中遍历字典键值,请使用for k,v in new.items()

IN: 
old = {1: 'one', 2: 'two'}
new = {1: 'new_one', 2: None, 3: 'new_three'}

old.update((k,v) for k,v in new.items() if v is not None)

Out:
old = {1: 'new_one', 2: 'two'}

0
如果您从一个转换为字典的 pydantic 对象中到达此处,则此方法不起作用。请改用 pydantic 函数 dict(exclude_none)。Python 3.7+ 例如,
     existing_job = db.query(MedicalRecord).filter(MedicalRecord.id == id)
else:
    existing_job = db.query(MedicalRecord).filter(MedicalRecord.id == id, MedicalRecord.owner_id==user.id)
if not existing_job.first():
    return 0
job.directory_hash = None



#doesnt work:
existing_job.update((k,v) for k,v in job.dict().items() if v is not None)
job = job.dict(exclude_none=True)
existing_job.update(job) # works

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接