Поиск ключа во вложенном словаре, смешанном со списками

#python #dictionary #recursion #nested

#python #словарь #рекурсия #вложенный

Вопрос:

Я получаю данные JSON обратно из API. Набор данных большой и вложенный. Я могу получить доступ к Datenreihen ключу следующим образом:

 jsondata.get("Ergebnis")[0].get("Kontakte").get("Datenreihen")
  

Как вы можете видеть, это смесь словарей и списков.

Я попробовал следующее, но со списками это не работает:-(.

 def recursive_lookup(k, d):
    if k in d:
        return d[k]
    for v in d.values():
        if isinstance(v, dict):
            return recursive_lookup(k, v)
    return None

# Works
recursive_lookup("Ergebnis", jsondata)

# Returns None
recursive_lookup("Datenreihen", jsondata)
  

Есть ли простой способ получить доступ и ключ в моем словаре, независимо от того, насколько глубоко вложен мой объект?

Это exampledata:

 {
    "Success":true,
    "Ergebnis":[
       {
          "ErgA1a: KPI Zeitreihe":{
             "Message":"",
             "MitZielgruppe":true,
             "Beschriftung":[
                "2019 KW 27",
                "2019 KW 28",
                "2019 KW 29"
             ],
             "Datenreihen":{
                "Gesamt":{
                   "Name":"Sympathie [#4]n(Sehr sympathisch, Sympathisch)",
                   "Werte":[
                      39.922142815641145,
                      37.751410794385762,
                      38.35504885993484
                   ]
                }
             }
          }
       }
    ],
    "rest":[
       {
          "test":"bla"
       }
    ]
 }

 data.get("ErgebnisseAnalyse")[0].get("ErgA1a: KPI Zeitreihe")

recursive_lookup("ErgA1a: KPI Zeitreihe", data)
  

Комментарии:

1. Можете ли вы привести простой пример данных, для которых он не работает?

2. обновленный вопрос

Ответ №1:

Рекурсивная функция для поиска значения во вложенном словаре на основе ключевого поля

Код

 def find_item(obj, field):
    """
    Takes a dict with nested lists and dicts,
    and searches all dicts for a key of the field
    provided.
    """
    if isinstance(obj, dict):
        for k, v in obj.items():
            if k == field:
                yield v
            elif isinstance(v, dict) or isinstance(v, list):
                yield from find_item(v, field)
    elif isinstance(obj, list):
        for v in obj:
            yield from find_item(v, field)
  

Использование

 value = next(find_item(dictionary_object, field), None)
  

Тест

 # Nested dictionary
dic = {
    "a": [{"b": {"c": 1}},
          {"d": 2}],
     "e": 3}

# Values form various fields
print(next(find_item(dic, "a"), None))  # Output: [{'b': {'c': 1}}, {'d': 2}]
print(next(find_item(dic, "b"), None))  # Output: {'c': 1}
print(next(find_item(dic, "c"), None))  # Output: 1
print(next(find_item(dic, "d"), None))  # Output: 2
print(next(find_item(dic, "e"), None))  # Output: 3
print(next(find_item(dic, "h"), None))  # Output: None