Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在嵌套字典中搜索关键字_Python - Fatal编程技术网

Python 在嵌套字典中搜索关键字

Python 在嵌套字典中搜索关键字,python,Python,我有一个Python中的JSON对象,表示为嵌套的字典列表。(字典的某些值是字典本身,依此类推。) 我希望能够在此嵌套字典结构的所有分支上搜索关键字。 当我找到密钥时,我希望能够返回指向它的完整密钥路径 例如:我正在寻找拥有“特殊地址密钥”的“特殊代理”,但并非所有的特殊代理都拥有它,以及那些在JSON中路径不一致的代理 因此,我搜索键特殊地址代码。 结果应返回: /'People'/'SpecialAgents'/'007'/'Special Address code'/ 因此,我将能够

我有一个Python中的JSON对象,表示为嵌套的字典列表。(字典的某些值是字典本身,依此类推。)

我希望能够在此嵌套字典结构的所有分支上搜索关键字。
当我找到密钥时,我希望能够返回指向它的完整密钥路径

例如:我正在寻找拥有“特殊地址密钥”的“特殊代理”,但并非所有的特殊代理都拥有它,以及那些在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']