猿问

更新不同深度的嵌套字典的值

更新不同深度的嵌套字典的值

我正在寻找一种方法来更新dict dictionary1与dict更新的内容wihout覆盖levelA

dictionary1={'level1':{'level2':{'levelA':0,'levelB':1}}}update={'level1':{'level2':{'levelB':10}}}dictionary1.update(update)print dictionary1{'level1': {'level2': {'levelB': 10}}}

我知道更新会删除level2中的值,因为它正在更新最低密钥level1。

鉴于dictionary1和update可以有任何长度,我怎么能解决这个问题呢?


米脂
浏览 885回答 3
3回答

浮云间

即递归解决方案,但有些特殊的编码和至少一个bug。我推荐,相反:import collectionsimport six# python 3.8+ compatibilitytry:     collectionsAbc = collections.abcexcept:     collectionsAbc = collectionsdef update(d, u):     for k, v in six.iteritems(u):         dv = d.get(k, {})         if not isinstance(dv, collectionsAbc.Mapping):             d[k] = v        elif isinstance(v, collectionsAbc.Mapping):             d[k] = update(dv, v)         else:             d[k] = v    return d该错误时显示“更新”有k,v项目在那里v是dict和k最初不是被更新在字典中的关键- @ FM代码“跳过”更新的这一部分(因为它执行它的新的空dict其没有保存或返回任何地方,只是在递归调用返回时丢失)。我的其他更改是次要的:没有理由if/ elseconstruct什么时候.get同一个工作更快更干净,并且isinstance最好应用于抽象基类(不是具体的)以获得通用性。

慕婉清6462132

对我说了一点,但多亏了@ Alex的帖子,他填补了我所缺少的空白。但是,如果递归中的值dict恰好是a ,我遇到了一个问题list,所以我想我会分享,并扩展他的答案。import collectionsdef update(orig_dict, new_dict):     for key, val in new_dict.iteritems():         if isinstance(val, collections.Mapping):             tmp = update(orig_dict.get(key, { }), val)             orig_dict[key] = tmp        elif isinstance(val, list):             orig_dict[key] = (orig_dict.get(key, []) + val)         else:             orig_dict[key] = new_dict[key]     return orig_dict

偶然的你

当用字典替换整数等元素时不起作用,例如update({'foo':0},{'foo':{'bar':1}})。此更新解决了它:import collectionsdef update(d, u):     for k, v in u.iteritems():         if isinstance(d, collections.Mapping):             if isinstance(v, collections.Mapping):                 r = update(d.get(k, {}), v)                 d[k] = r            else:                 d[k] = u[k]         else:             d = {k: u[k]}     return d update({'k1': 1}, {'k1': {'k2': {'k3': 3}}})
随时随地看视频慕课网APP

相关分类

Python
我要回答