我得到了一个json结构,其中包含字符串、列表、字典和字典列表。深度是任意的,但所有字典都有一个"name"键。
我需要做两件事。1( 找到某个键的所有键值,我用下面的方法找到了这个,但它看起来很笨重。。。
def find_all_keys(db, search_key):
key_found_list = []
for key, value in db.items():
if key == search_key:
key_found_list.append(value)
elif isinstance(value, dict):
resultsA = find_all_keys(value, search_key)
for result in resultsA:
key_found_list.append(result)
elif isinstance(value, list):
for item in value:
if isinstance(item, dict):
resultsB = find_all_keys(item, search_key)
for result_outofnames in resultsB:
key_found_list.append(result_outofnames)
return key_found_list
第二部分。
字典的每个级别都有一个名为name的属性,name是一个字符串。
我试图查找某个名称的值,如果找到了,请在此之前查找"name"的所有其他值。
因此,例如键"name"one_answers"value"some321应该返回路径列表,例如:md->level0->level1->be->some321
在第一次点击时填写一个列表似乎相对容易,但我不能只在找到结果的情况下填写列表。我有什么好办法吗?
下面是我多次失败尝试中的一次:
def find_key_value_path(db, search_key, search_value):
key_value_path_list = []
for key, value in db.items():
if key == search_key:
print("found key: ", key)
if value == search_value:
print("found value in key", value, key)
key_value_path_list.append(value)
elif isinstance(value, dict):
results = find_key_value_path(value, search_key)
for result in results:
key_value_path_list.append(result)
elif isinstance(value, list):
for item in value:
if isinstance(item, dict):
more_results = find_key_value_path(item, search_key)
for another_result in more_results:
key_value_path_list.append(another_result)
return key_value_path_list
很抱歉添加json输入的示例:
{
"name": "/",
"device_count": 91,
"num_ports": 3,
"devices": [],
"childnodes": [
{
"name": "mm",
"device_count": 0,
"num_ports": 3,
"devices": [],
"childnodes": [
{
"name": "mynode",
"device_count": 0,
"num_ports": 3,
"devices": [],
"childnodes": [],
"type": "group"
}
],
"type": "group"
},
{
"name": "md",
"device_count": 91,
"num_ports": 4,
"devices": [],
"childnodes": [
{
"name": “level0,
"device_count": 91,
"num_ports": 4,
"devices": [],
"childnodes": [
{
"name": "level1”,
"device_count": 6,
"num_ports": 6,
"devices": [],
"childnodes": [
{
"name": "level2”,
"device_count": 2,
"num_ports": 6,
"devices": [
{
"name": “something1”,
"longitude": "",
"mac": "00:1a:1e:04:a9:d0",
"num_ports": 6,
"latitude": "",
"type": "A7240XM"
},
{
"name": “something2”,
"longitude": "",
"mac": "00:1a:1e:04:aa:d0",
"num_ports": 6,
"latitude": "",
"type": "A7240XM"
}
],
"childnodes": [],
"type": "group"
},
{
"name": "ng",
"device_count": 2,
"num_ports": 6,
"devices": [
{
"name": “someother1”,
"longitude": "",
"mac": "00:1a:1e:05:4e:b8",
"num_ports": 6,
"latitude": "",
"type": "A7240XM"
},
{
"name": “findME,
"longitude": "",
"mac": "00:1a:1e:05:4d:e8",
"num_ports": 6,
"latitude": "",
"type": "A7240XM"
}
],
"childnodes": [],
"type": "group"
},
{
"name": “be”,
"device_count": 2,
"num_ports": 6,
"devices": [
{
"name": “some123”,
"longitude": "",
"mac": "00:1a:1e:05:4e:b8",
"num_ports": 6,
"latitude": "",
"type": "A7240XM"
},
{
"name": “some321”,
"longitude": "",
"mac": "00:1a:1e:05:4d:e8",
"num_ports": 6,
"latitude": "",
"type": "A7240XM"
}
],
"childnodes": [],
"type": "group"
},
您应该使用yield来创建迭代器。它将使代码更简单、更高效(尤其是如果您不打算总是遍历所有出现的情况(。要只找到第一个,可以使用下一个函数。
def findKeys(d,key,value):
if key in d and d[key] == value: yield [d["name"]]
subLevels = ( (a,v) for a,vl in d.items() if isinstance(vl,list) for v in vl )
for attrib,subDict in subLevels:
if not isinstance(subDict,dict):continue
for path in findKeys(subDict,key,value):
yield [d["name"]]+path
输出:
for path in findKeys(d,"type","A7240XM"):
print(path)
['/', 'md', 'level0', 'level1', 'level2', 'something1']
['/', 'md', 'level0', 'level1', 'level2', 'something2']
['/', 'md', 'level0', 'level1', 'ng', 'someother1']
['/', 'md', 'level0', 'level1', 'ng', 'findME']
['/', 'md', 'level0', 'level1', 'be', 'some123']
['/', 'md', 'level0', 'level1', 'be', 'some321']
]
next(findKeys(d,"name","some123"))
['/', 'md', 'level0', 'level1', 'be', 'some123']