在嵌套字典和列表中查找键、值对的出现路径
Find path of occurrences of a key, value pair in nested dictionaries and lists
我得到了一个 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" 和 "value" some321 应该 return 路径列表,例如:
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 来创建迭代器。这将使代码更简单、更高效(特别是如果您不打算总是经历所有事件)。要只找第一个,可以用next函数。
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']
我得到了一个 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" 和 "value" some321 应该 return 路径列表,例如: 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 来创建迭代器。这将使代码更简单、更高效(特别是如果您不打算总是经历所有事件)。要只找第一个,可以用next函数。
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']