Python 在嵌套字典中搜索关键字
我有一个Python中的JSON对象,表示为嵌套的字典列表。(字典的某些值是字典本身,依此类推。) 我希望能够在此嵌套字典结构的所有分支上搜索关键字。Python 在嵌套字典中搜索关键字,python,Python,我有一个Python中的JSON对象,表示为嵌套的字典列表。(字典的某些值是字典本身,依此类推。) 我希望能够在此嵌套字典结构的所有分支上搜索关键字。 当我找到密钥时,我希望能够返回指向它的完整密钥路径 例如:我正在寻找拥有“特殊地址密钥”的“特殊代理”,但并非所有的特殊代理都拥有它,以及那些在JSON中路径不一致的代理 因此,我搜索键特殊地址代码。 结果应返回: /'People'/'SpecialAgents'/'007'/'Special Address code'/ 因此,我将能够
当我找到密钥时,我希望能够返回指向它的完整密钥路径 例如:我正在寻找拥有“特殊地址密钥”的“特殊代理”,但并非所有的特殊代理都拥有它,以及那些在JSON中路径不一致的代理 因此,我搜索键
特殊地址代码
。
结果应返回:
/'People'/'SpecialAgents'/'007'/'Special Address code'/
因此,我将能够通过这种方式获取其信息:
json_obj['People']['SpecialAgents']['007']['Special Address code']
请注意,这与类似,但我需要找到的密钥的每个实例的完整路径。您需要搜索树。这是最简单的方法 可以对其进行增强—例如,最好使用None作为默认参数值,而不是某个对象。此外,这是深度优先搜索-您可能只想得到一个结果,而宽度优先搜索更好(如果您不知道,请在维基百科上阅读这两个术语)
你需要一个递归搜索 您可以定义一个函数来深入搜索输入json:
def find_in_obj(obj, condition, path=None):
if path is None:
path = []
# In case this is a list
if isinstance(obj, list):
for index, value in enumerate(obj):
new_path = list(path)
new_path.append(index)
for result in find_in_obj(value, condition, path=new_path):
yield result
# In case this is a dictionary
if isinstance(obj, dict):
for key, value in obj.items():
new_path = list(path)
new_path.append(key)
for result in find_in_obj(value, condition, path=new_path):
yield result
if condition == key:
new_path = list(path)
new_path.append(key)
yield new_path
然后,我们可以使用本文中的示例JSON来测试递归搜索:
In [15]: my_json = { "id" : "abcde",
....: "key1" : "blah",
....: "key2" : "blah blah",
....: "nestedlist" : [
....: { "id" : "qwerty",
....: "nestednestedlist" : [
....: { "id" : "xyz",
....: "keyA" : "blah blah blah" },
....: { "id" : "fghi",
....: "keyZ" : "blah blah blah" }],
....: "anothernestednestedlist" : [
....: { "id" : "asdf",
....: "keyQ" : "blah blah" },
....: { "id" : "yuiop",
....: "keyW" : "blah" }] } ] }
让我们找到键“id”的每个实例,并返回到达该键的完整路径:
In [16]: for item in find_in_obj(my_json, 'id'):
....: print item
....:
['nestedlist', 0, 'nestednestedlist', 0, 'id']
['nestedlist', 0, 'nestednestedlist', 1, 'id']
['nestedlist', 0, 'id']
['nestedlist', 0, 'anothernestednestedlist', 0, 'id']
['nestedlist', 0, 'anothernestednestedlist', 1, 'id']
['id']
听起来您需要一个类似于XPath的JSON。有几个例子。如果有多个相同的键怎么办?另请参见:这是仅python3的语法,您也不需要调用.keys来迭代dict keystld ya,这可能需要一些增强功能:P另一个丑陋的事情是使用isinstance(),但这不是重点。此外,我认为“仅python3”并不是一件坏事——我强烈支持迁移到新的行而不是使用p2.7。好吧,直到pythons fairy Godmar出现并单击她的手指,使所有编写的python代码与python3兼容,我想python2代码仍然需要编写。我看不出
isinstance()
有任何问题,这与键不同;)固定的。无论如何,唯一的区别是,在p2中,你应该使用x中的x:yield x,而不是x中的yield。更多信息:如果有人想看+1,这是可行的。美好的我从中搜索对象中的id
,对其进行了测试。对它的工作原理有什么评论吗?你从哪里得到的?(所有这些代码都是从头开始编写的吗?@LondonRob此函数迭代键并存储当前路径的状态。它基于收益率(这简化了解决方案)。从头开始写,然后是OP descriptionMind,如果我稍微编辑一下以显示更完整的示例?它比你目前的单一结果更好地显示了你的工作。@LondonRob可以随意改进这个答案(以及本网站上的任何其他答案:P)
In [16]: for item in find_in_obj(my_json, 'id'):
....: print item
....:
['nestedlist', 0, 'nestednestedlist', 0, 'id']
['nestedlist', 0, 'nestednestedlist', 1, 'id']
['nestedlist', 0, 'id']
['nestedlist', 0, 'anothernestednestedlist', 0, 'id']
['nestedlist', 0, 'anothernestednestedlist', 1, 'id']
['id']