折腾:
期间,需要去处理:
把a和b两个dict合并:
book_common.json
<code>{ "title": "Gitbook的书名", "description": "gitbook书的描述", "author": "Crifan Li <[email protected]>", "language": "zh-hans", "gitbook": "3.2.3", "root": "./src", "links": { "sidebar": { "主页": "https://www.crifan.com" } }, "plugins": [ "theme-comscore", "-lunr", "-search", "search-plus", "disqus", "-highlight", "prism", "prism-themes", "github-buttons", "splitter", "-sharing", "sharing-plus", "tbfed-pagefooter", "expandable-chapters-small", "ga", "donate", "sitemap-general", "copy-code-button", "-alerts", "-bootstrap-callout", "callouts", "toolbar-button" ], "pluginsConfig": { "callouts": { "showTypeInHeader": false }, "theme-default": { "showLevel": true }, "disqus": { "shortName": "crifan" }, "prism": { "css": [ "prism-themes/themes/prism-atom-dark.css" ] }, "github-buttons": { "buttons": [ { "user": "crifan", "repo": "gitbook_name", "type": "star", "count": true, "size": "small" }, { "user": "crifan", "type": "follow", "width": "120", "count": false, "size": "small" } ] }, "sharing": { "douban": false, "facebook": true, "google": false, "hatenaBookmark": false, "instapaper": false, "line": false, "linkedin": false, "messenger": false, "pocket": false, "qq": true, "qzone": false, "stumbleupon": false, "twitter": true, "viber": false, "vk": false, "weibo": true, "whatsapp": false, "all": [ "douban", "facebook", "google", "instapaper", "line", "linkedin", "messenger", "pocket", "qq", "qzone", "stumbleupon", "twitter", "viber", "vk", "weibo", "whatsapp" ] }, "tbfed-pagefooter": { "copyright": "crifan.com,使用<a href='https://creativecommons.org/licenses/by-sa/4.0/deed.zh'>知识署名-相同方式共享4.0协议</a>发布", "modify_label": "该文件修订时间:", "modify_format": "YYYY-MM-DD HH:mm:ss" }, "ga": { "token": "UA-28297199-1" }, "donate": { "wechat": "https://www.crifan.com/files/res/crifan_com/crifan_wechat_pay.jpg", "alipay": "https://www.crifan.com/files/res/crifan_com/crifan_alipay_pay.jpg", "title": "", "button": "打赏", "alipayText": "支付宝打赏给Crifan", "wechatText": "微信打赏给Crifan" }, "sitemap-general": { "prefix": "https://book.crifan.com/gitbook/gitbook_name/website/" }, "toolbar-button": { "icon": "fa-file-pdf-o", "label": "下载PDF", "url": "http://book.crifan.com/books/gitbook_name/pdf/gitbook_name.pdf" } } } </code>
book_current.json
<code>{ "title": "有道云笔记和云协作使用总结", "description": "总结之前使用过有道云笔记和有道云协作的心得供参考", "pluginsConfig": { "github-buttons": { "buttons": [ { "repo": "youdao_note_summary" } ] }, "sitemap-general": { "prefix": "https://book.crifan.com/gitbook/youdao_note_summary/website/" }, "toolbar-button": { "url": "http://book.crifan.com/books/youdao_note_summary/pdf/youdao_note_summary.pdf" } } } </code>
希望合并后是:
<code>{ "title": "有道云笔记和云协作使用总结", "description": "总结之前使用过有道云笔记和有道云协作的心得供参考", "author": "Crifan Li <[email protected]>", "language": "zh-hans", "gitbook": "3.2.3", "root": "./src", "links": { "sidebar": { "主页": "https://www.crifan.com" } }, "plugins": [ "theme-comscore", "-lunr", "-search", "search-plus", "disqus", "-highlight", "prism", "prism-themes", "github-buttons", "splitter", "-sharing", "sharing-plus", "tbfed-pagefooter", "expandable-chapters-small", "ga", "donate", "sitemap-general", "copy-code-button", "-alerts", "-bootstrap-callout", "callouts", "toolbar-button" ], "pluginsConfig": { "callouts": { "showTypeInHeader": false }, "theme-default": { "showLevel": true }, "disqus": { "shortName": "crifan" }, "prism": { "css": [ "prism-themes/themes/prism-atom-dark.css" ] }, "github-buttons": { "buttons": [ { "user": "crifan", "repo": "youdao_note_summary", "type": "star", "count": true, "size": "small" }, { "user": "crifan", "type": "follow", "width": "120", "count": false, "size": "small" } ] }, "sharing": { "douban": false, "facebook": true, "google": false, "hatenaBookmark": false, "instapaper": false, "line": false, "linkedin": false, "messenger": false, "pocket": false, "qq": true, "qzone": false, "stumbleupon": false, "twitter": true, "viber": false, "vk": false, "weibo": true, "whatsapp": false, "all": [ "douban", "facebook", "google", "instapaper", "line", "linkedin", "messenger", "pocket", "qq", "qzone", "stumbleupon", "twitter", "viber", "vk", "weibo", "whatsapp" ] }, "tbfed-pagefooter": { "copyright": "crifan.com,使用<a href='https://creativecommons.org/licenses/by-sa/4.0/deed.zh'>知识署名-相同方式共享4.0协议</a>发布", "modify_label": "该文件修订时间:", "modify_format": "YYYY-MM-DD HH:mm:ss" }, "ga": { "token": "UA-28297199-1" }, "donate": { "wechat": "https://www.crifan.com/files/res/crifan_com/crifan_wechat_pay.jpg", "alipay": "https://www.crifan.com/files/res/crifan_com/crifan_alipay_pay.jpg", "title": "", "button": "打赏", "alipayText": "支付宝打赏给Crifan", "wechatText": "微信打赏给Crifan" }, "sitemap-general": { "prefix": "https://book.crifan.com/gitbook/youdao_note_summary/website/" }, "toolbar-button": { "icon": "fa-file-pdf-o", "label": "下载PDF", "url": "http://book.crifan.com/books/youdao_note_summary/pdf/youdao_note_summary.pdf" } } } </code>
python json merge
python dict merge
How to merge two json string in Python? – Stack Overflow
python – How to merge two dictionaries in a single expression? – Stack Overflow
去试试效果
结果:
<code>bookJson = {**templateJson, **currentJson} pprint(bookJson) </code>
合并后是:
<code>{ 'root': './src', 'title': '有道云笔记和云协作使用总结', 'author': 'Crifan Li <[email protected]>', 'description': '总结之前使用过有道云笔记和有道云协作的心得供参考', 'gitbook': '3.2.3', 'language': 'zh-hans', 'links': { 'sidebar': { '主页': 'https://www.crifan.com' } }, 'plugins': [ 'theme-comscore', '-lunr', '-search', 'search-plus', 'disqus', '-highlight', 'prism', 'prism-themes', 'github-buttons', 'splitter', '-sharing', 'sharing-plus', 'tbfed-pagefooter', 'expandable-chapters-small', 'ga', 'donate', 'sitemap-general', 'copy-code-button', '-alerts', '-bootstrap-callout', 'callouts', 'toolbar-button' ], 'pluginsConfig': { 'github-buttons': { 'buttons': [{ 'repo': 'youdao_note_summary' }] }, 'sitemap-general': { 'prefix': 'https://book.crifan.com/gitbook/youdao_note_summary/website/' }, 'toolbar-button': { 'url': 'http://book.crifan.com/books/youdao_note_summary/pdf/youdao_note_summary.pdf' } } } </code>
其中基本的字段,比如title和description,是合并update了的
但是pluginsConfig的部分,只有后者,没有前面的值了。
试试别的方案
<code>bookJson = templateJson.copy() bookJson.update(currentJson) pprint(bookJson) </code>
问题依旧:
<code>bookJson = dict(templateJson, **currentJson) </code>
问题依旧。
<code>from collections import ChainMap bookJson = ChainMap({}, currentJson, templateJson) print("type(bookJson)=", type(bookJson)) </code>
问题依旧。
<code>def recursiveUpdateDict(original, update): """ Recursively update a dict. Subdict's won't be overwritten but also updated. """ for key, value in original.iteritems(): if key not in update: update[key] = value elif isinstance(value, dict): recursiveUpdateDict(value, update[key]) return update bookJson = recursiveUpdateDict(templateJson, currentJson) </code>
但是出错:
<code> for key, value in original.iteritems(): AttributeError: 'dict' object has no attribute 'iteritems' </code>
AttributeError: ‘dict’ object has no attribute ‘iteritems’
AttributeError: ‘dict’ object has no attribute ‘iteritems’ – CSDN博客
Python3下AttributeError: ‘dict’ object has no attribute ‘iteritems’的问题分析 – CSDN博客
改为:
<code>def recursiveUpdateDict(original, update): """ Recursively update a dict. Subdict's won't be overwritten but also updated. """ # for key, value in original.iteritems(): for key, value in original.items(): if key not in update: update[key] = value elif isinstance(value, dict): recursiveUpdateDict(value, update[key]) return update bookJson = recursiveUpdateDict(templateJson, currentJson) </code>
结果:
好像是可以的。
再去升级代码,支持Python2和Python3:
经过优化后,完整代码是:
<code>from pprint import pprint import sys templateJson = {} currentJson = {} 。。。 def recursiveMergeDict(originalDict, toMergeDict): """ Recursively update a dict. Sub dict's won't be overwritten but also updated. """ originalDictItems = None if (sys.version_info[0] == 2): # is python 2 originalDictItems = originalDict.iteritems() else: originalDictItems = originalDict.items() mergedDict = toMergeDict.copy() for key, value in originalDictItems: if key not in mergedDict: mergedDict[key] = value elif isinstance(value, dict): recursiveMergeDict(value, mergedDict[key]) return mergedDict bookJson = recursiveMergeDict(templateJson, currentJson) pprint("-"*80) pprint(bookJson) pprint("-"*80) pprint(currentJson) </code>
效果:
可见,merge后,a和b中的b,也是没有被修改的,而是返回a和b合并后的结果c的。
【后记1】
后来发现上述写法有问题:
传入a和b,结果b会被修改
而上面的写法,没法起到递归的效果
【后记2】
折腾了:
【已解决】python中把dict的json输出到文件且带缩进和不要unicode的\uxxxx
后,输出的结果是:
<code>{ "description": "总结之前使用过有道云笔记和有道云协作的心得供参考", "links": { "sidebar": { "主页": "https://www.crifan.com" } }, "author": "Crifan Li <[email protected]>", "title": "有道云笔记和云协作使用总结", "gitbook": "3.2.3", "language": "zh-hans", "plugins": [ "theme-comscore", "-lunr", "-search", "search-plus", "disqus", "-highlight", "prism", "prism-themes", "github-buttons", "splitter", "-sharing", "sharing-plus", "tbfed-pagefooter", "expandable-chapters-small", "ga", "donate", "sitemap-general", "copy-code-button", "-alerts", "-bootstrap-callout", "callouts", "toolbar-button" ], "pluginsConfig": { "toolbar-button": { "url": "http://book.crifan.com/books/youdao_note_summary/pdf/youdao_note_summary.pdf", "icon": "fa-file-pdf-o", "label": "下载PDF" }, "sitemap-general": { "prefix": "https://book.crifan.com/gitbook/youdao_note_summary/website/" }, "sharing": { "qq": true, "douban": false, "all": [ "douban", "facebook", "google", "instapaper", "line", "linkedin", "messenger", "pocket", "qq", "qzone", "stumbleupon", "twitter", "viber", "vk", "weibo", "whatsapp" ], "google": false, "stumbleupon": false, "hatenaBookmark": false, "twitter": true, "vk": false, "linkedin": false, "instapaper": false, "pocket": false, "weibo": true, "viber": false, "facebook": true, "qzone": false, "messenger": false, "line": false, "whatsapp": false }, "tbfed-pagefooter": { "modify_format": "YYYY-MM-DD HH:mm:ss", "modify_label": "该文件修订时间:", "copyright": "crifan.com,使用<a href='https://creativecommons.org/licenses/by-sa/4.0/deed.zh'>知识署名-相同方式共享4.0协议</a>发布" }, "github-buttons": { "buttons": [ { "repo": "youdao_note_summary" } ] }, "disqus": { "shortName": "crifan" }, "prism": { "css": [ "prism-themes/themes/prism-atom-dark.css" ] }, "ga": { "token": "UA-28297199-1" }, "theme-default": { "showLevel": true }, "donate": { "alipay": "https://www.crifan.com/files/res/crifan_com/crifan_alipay_pay.jpg", "title": "", "alipayText": "支付宝打赏给Crifan", "button": "打赏", "wechatText": "微信打赏给Crifan", "wechat": "https://www.crifan.com/files/res/crifan_com/crifan_wechat_pay.jpg" }, "callouts": { "showTypeInHeader": false } }, "root": "./src" } </code>
其中大部分的json的内容,是合并对了。
但是部分内容,并没有合并更新:
对于:
<code> "github-buttons": { "buttons": [ { "user": "crifan", "repo": "gitbook_name", "type": "star", "count": true, "size": "small" }, { "user": "crifan", "type": "follow", "width": "120", "count": false, "size": "small" } ] }, </code>
和:
<code> "github-buttons": { "buttons": [ { "repo": "youdao_note_summary" } ] }, </code>
结果是:
<code> "github-buttons": { "buttons": [ { "repo": "youdao_note_summary" } ] }, </code>
其实希望的是
<code> "github-buttons": { "buttons": [ { "user": "crifan", "repo": "youdao_note_summary", "type": "star", "count": true, "size": "small" }, { "user": "crifan", "type": "follow", "width": "120", "count": false, "size": "small" } ] }, </code>
所以前面的合并算法还是有问题。
去优化
【总结】
最后用代码:
<code>def recursiveMergeDict(aDict, bDict): """ Recursively merge dict a to b, return merged dict b Note: Sub dict's won't be overwritten but also updated/merged """ aDictItems = None if (sys.version_info[0] == 2): # is python 2 aDictItems = aDict.iteritems() else: # is python 3 aDictItems = aDict.items() for aKey, aValue in aDictItems: print("------ [%s]=%s" % (aKey, aValue)) if aKey not in bDict: bDict[aKey] = aValue else: bValue = bDict[aKey] print("aValue=%s" % aValue) print("bValue=%s" % bValue) if isinstance(aValue, dict): recursiveMergeDict(aValue, bValue) elif isinstance(aValue, list): aValueListLen = len(aValue) bValueListLen = len(bValue) bValueListMaxIdx = bValueListLen - 1 for aListIdx in range(aValueListLen): print("---[%d]" % aListIdx) aListItem = aValue[aListIdx] print("aListItem=%s" % aListItem) if aListIdx <= bValueListMaxIdx: bListItem = bValue[aListIdx] print("bListItem=%s" % bListItem) recursiveMergeDict(aListItem, bListItem) else: # recursiveMergeDict(aListItem, aListItem) print("bDict=%s" % bDict) print("aKey=%s" % aKey) print("aListItem=%s" % aListItem) bDict[aKey].append(aListItem) return bDict bookJson = recursiveMergeDict(templateJson, copy.deepcopy(currentJson)) pprint("-a"*40) pprint(templateJson) pprint("-b"*40) pprint(currentJson) pprint("-c"*40) pprint(bookJson) </code>
输出:
<code>'-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a' {u'pluginsConfig': {u'github-buttons': {u'buttons': [{u'count': True, u'repo': u'gitbook_name', u'size': u'small', u'type': u'star', u'user': u'crifan'}, {u'count': False, u'size': u'small', u'type': u'follow', u'user': u'crifan', u'width': u'120'}, {u'key1': u'string1', u'key2': 999, u'key3': True}]}}} '-b-b-b-b-b-b-b-b-b-b-b-b-b-b-b-b-b-b-b-b-b-b-b-b-b-b-b-b-b-b-b-b-b-b-b-b-b-b-b-b' {u'pluginsConfig': {u'github-buttons': {u'buttons': [{u'repo': u'youdao_note_summary'}]}}} '-c-c-c-c-c-c-c-c-c-c-c-c-c-c-c-c-c-c-c-c-c-c-c-c-c-c-c-c-c-c-c-c-c-c-c-c-c-c-c-c' {u'pluginsConfig': {u'github-buttons': {u'buttons': [{u'count': True, u'repo': u'youdao_note_summary', u'size': u'small', u'type': u'star', u'user': u'crifan'}, {u'count': False, u'size': u'small', u'type': u'follow', u'user': u'crifan', u'width': u'120'}, {u'key1': u'string1', u'key2': 999, u'key3': True}]}}} </code>
实现了希望看到的效果:
合并a和b的dict
如果包含子dict,则递归去合并
如果包含list,则针对每个item去合并
如果a的list比b多,则保留a多出的部分
转载请注明:在路上 » 【已解决】Python中实现dict的递归的合并更新