在嵌套字典和列表中查找键、值对的出现路径



我得到了一个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']

相关内容

  • 没有找到相关文章

最新更新