【问题标题】:Find path of occurrences of a key, value pair in nested dictionaries and lists [closed]在嵌套字典和列表中查找键、值对的出现路径[关闭]
【发布时间】:2020-03-24 00:03:16
【问题描述】:

我在字符串、列表、字典和字典列表的字典中得到了一个 json 结构。深度是任意的,但所有字典都有“名称”键。

我需要做两件事。 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的属性,它是一个字符串。

我正在尝试查找某个名称的值,如果找到,则在此之前查找“名称”的所有其他值。

因此,例如 key "name" 和 "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"
                },

【问题讨论】:

  • 您的示例中有一堆无效引号,并且它没有正确关闭大括号,因此如果没有比大多数人愿意为您提供帮助的更多工作,它基本上无法使用。

标签: python dictionary path nested nested-lists


【解决方案1】:

你应该使用 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']

【讨论】:

  • 非常感谢,效果很好。我仍在努力了解您的次级线和继续线。但会分解成更小的部分,看看它是如何工作的。
猜你喜欢
  • 2012-04-06
  • 2022-06-15
  • 2017-12-27
  • 1970-01-01
  • 2021-11-30
  • 2015-08-05
  • 2018-11-02
  • 2015-09-11
相关资源
最近更新 更多