Python 循环浏览字典并跟踪关键点深度
我想比较两本字典。目标是找出哪些键在之前存在,但在之后不存在(丢失),以及匹配键中更改了哪些值(更改) 我有一个伪工作脚本,但问题是它没有显示更改的键/值对所属的所有键Python 循环浏览字典并跟踪关键点深度,python,json,python-2.7,loops,dictionary,Python,Json,Python 2.7,Loops,Dictionary,我想比较两本字典。目标是找出哪些键在之前存在,但在之后不存在(丢失),以及匹配键中更改了哪些值(更改) 我有一个伪工作脚本,但问题是它没有显示更改的键/值对所属的所有键 import json from pprint import pprint def new_keys(d1, d2, result={}): for key in d1.keys(): if not d2.has_key(key): result[key] = d1[key]
import json
from pprint import pprint
def new_keys(d1, d2, result={}):
for key in d1.keys():
if not d2.has_key(key):
result[key] = d1[key]
else:
if isinstance(d1[key], dict) and isinstance(d2[key], dict):
new_keys(d1[key], d2[key], result)
else:
if d1[key] != d2[key]:
result[key] = d2[key]
return result
with open("before.json") as data_file:
before = json.loads(data_file.read())
with open("after.json") as data_file:
after = json.loads(data_file.read())
pprint(new_keys(before,after))
目前的结果是:
{u'1.1.1.1/32': {u'directlyConnected': True,
u'hardwareProgrammed': True,
u'kernelProgrammed': True,
u'routeAction': u'drop',
u'routeType': u'static',
u'vias': []},
我想要的一个示例结果是:(它是一个不同的路由0.0.0.0/0,而不是1.1.1.1/32),但请注意,它嵌套在vrfs(默认)路由键中
{u'vrfs': {u'default': {u'allRoutesProgrammedHardware': True,
u'allRoutesProgrammedKernel': True,
u'defaultRouteState': u'reachable',
u'routes': {u'0.0.0.0/0': {u'directlyConnected': False,
u'hardwareProgrammed': True,
u'kernelProgrammed': True,
u'metric': 0,
u'preference': 1,
u'routeAction': u'forward',
u'routeType': u'static',
u'vias': [{u'interface': u'Management1',
u'nexthopAddr': u'10.31.32.1'}]},
我怀疑我需要在更深一步时以某种方式跟踪关键点,但我很难对其进行适当的编码
非常感谢您的帮助
编辑:示例JSON
{
"vrfs": {
"default": {
"routes": {
"2.2.2.2/32": {
"kernelProgrammed": true,
"directlyConnected": true,
"routeAction": "forward",
"vias": [
{
"interface": "Ethernet4"
}
],
"hardwareProgrammed": true,
"routeType": "static"
}
},
"allRoutesProgrammedKernel": true,
"routingDisabled": false,
"allRoutesProgrammedHardware": true,
"defaultRouteState": "reachable"
}
}
}
在-
{
"vrfs": {
"default": {
"routes": {
"2.2.2.2/32": {
"kernelProgrammed": true,
"directlyConnected": true,
"routeAction": "forward",
"vias": [
{
"interface": "Ethernet9"
}
],
"hardwareProgrammed": true,
"routeType": "static"
}
},
"allRoutesProgrammedKernel": true,
"routingDisabled": false,
"allRoutesProgrammedHardware": true,
"defaultRouteState": "reachable"
}
}
}
接口值已更改。根据我上面的评论,这里有一个可能的解决方案。还有一些肾盂的改进。使用
iteritems()
import json
from pprint import pprint
def new_keys(d1, d2, result={}):
for key, d1_val in d1.iteritems():
if key not in d2:
result[key] = d1_val
else:
if isinstance(d1_val, dict) and isinstance(d2[key], dict):
# Don't pass result.
new_result = {}
new_keys(d1[key], d2[key], new_result)
# If new_result is not empty
if new_result:
result[key] = new_result
else:
if d1_val != d2[key]:
result[key] = d1_val
return result
with open("before.json") as data_file:
before = json.loads(data_file.read())
with open("after.json") as data_file:
after = json.loads(data_file.read())
pprint(new_keys(before,after))
对于json前后的示例,这就是我得到的
{u'vrfs': {u'default': {u'routes': {u'2.2.2.2/32': {u'vias': [{u'interface': u'Ethernet4'}]}}}}}
根据我上面的评论,这里有一个可能的解决方案。还有一些肾盂的改进。使用iteritems()
import json
from pprint import pprint
def new_keys(d1, d2, result={}):
for key, d1_val in d1.iteritems():
if key not in d2:
result[key] = d1_val
else:
if isinstance(d1_val, dict) and isinstance(d2[key], dict):
# Don't pass result.
new_result = {}
new_keys(d1[key], d2[key], new_result)
# If new_result is not empty
if new_result:
result[key] = new_result
else:
if d1_val != d2[key]:
result[key] = d1_val
return result
with open("before.json") as data_file:
before = json.loads(data_file.read())
with open("after.json") as data_file:
after = json.loads(data_file.read())
pprint(new_keys(before,after))
对于json前后的示例,这就是我得到的
{u'vrfs': {u'default': {u'routes': {u'2.2.2.2/32': {u'vias': [{u'interface': u'Ethernet4'}]}}}}}
由于需要嵌套的dict,因此不应传递相同的结果dict。因此,对于对new_keys()
的每次调用,您应该传入一个新的结果
dict,然后将值存储在调用方迭代中。如果您可以在json发布前后发布一个示例helpful@WreckeR我已经为before/after添加了示例json数据。这是我的第一个python脚本,如果您能向我展示示例代码来解释您的观点,我将不胜感激。因为您需要嵌套的dict,所以不应该传递相同的结果dict。因此,对于对new_keys()
的每次调用,您应该传入一个新的结果
dict,然后将值存储在调用方迭代中。如果您可以在json发布前后发布一个示例helpful@WreckeR我已经为before/after添加了示例json数据。这是我的第一个python脚本,如果您能向我展示示例代码来解释您的观点,我将不胜感激。我不知道这个示例中的递归将如何工作并适当跟踪深度。不确定我做错了什么,可能是粘贴错误,但是我得到了不同的输出。这里的关键是new\u result
。如果递归中的任何一点,new_result不是空的,那么树上的每个路径现在都将有一个非空的new_result
在看到您的示例后,我已经更新了我的代码。此外,我还必须向循环中的每个调用new_keys()
明确地传递一个空的结果。这太棒了。我不知道这个例子中的递归是如何工作的,也不知道如何正确地跟踪深度。不确定我做错了什么,可能是粘贴错误,但我得到了不同的输出。这里的关键是new\u result
。如果递归中的任何一点,new_result不是空的,那么树上的每个路径现在都将有一个非空的new_result
在看到您的示例后,我已经更新了我的代码。此外,我还必须向循环中的每个调用new_keys()
明确地传递一个空的结果。这太棒了。