Как разобрать сложный вложенный словарь и распечатать все ключи, отсортированные внутри вложенного словаря в python?

#python

#python

Вопрос:

У меня есть следующие данные

 a = {'globe': {'first_entry': 0,
                     'first_messanger': 100,
                     'galaxy': 7},
 'earth': {'secondary_messanger': 9,
                 'earth_forecast': {'avg_temp': 60,
                                       'zip_code': 10001,
                                       'city_name': 'New York',
                                       'forecast': [{'day': 'Monday',
                                                           'temp': '70'},
                                                          {'day': 'Tuesday',
                                                           'temp': '71'},
                                                          {'day': 'Wednesday',
                                                           'temp': '60'}]}}}
 

Я пробовал с помощью кода

 def parsingvalue(b):

    lst = []
    for key, value in b.items():
        if isinstance(value, dict):
            tmp = value.keys()
            for i in tmp:
                lst.append(i)
        lst.append (key)
    print (sorted(lst))

parsingvalue (a)
 

С помощью этого кода мой вывод ['earth', 'earth_forecast', 'first_entry', 'first_messanger', 'galaxy', 'globe', 'secondary_messanger']

Вывод отсутствует 'avg_temp', 'zip_code', 'city_name', 'forecast', 'day', 'temp'

Вопрос: Как я могу улучшить код, чтобы вывод также включал отсутствующие ключевые элементы?

Ответ №1:

Вам нужно вызвать функцию рекурсивно, поскольку они состоят из нескольких слоев:

 def get_all_keys(d, res=None):
    if res is None:
        res = []
    for k in d:
        res.append(k)
        if isinstance(d[k], dict):
            get_all_keys(d[k], res)
        if isinstance(d[k], list):
            for i in d[k]:
                if isinstance(i, dict):
                    get_all_keys(i, res)
    return res

ret = get_all_keys(a)
list(set(ret))
 

Дает:

 ['forecast',
 'secondary_messanger',
 'first_entry',
 'zip_code',
 'day',
 'galaxy',
 'first_messanger',
 'temp',
 'earth',
 'globe',
 'city_name',
 'avg_temp',
 'earth_forecast']
 

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

1. @Z Li — Большое спасибо. Это работает отлично.

Ответ №2:

Почти то же решение, что и у @z-li, который использует рекурсивный трюк, но только с одним тестом на экземпляре dict, используя генератор вместо передачи списка, и немного более надежный, поскольку он не предполагает, что ввод является dict:

 def get_all_keys(d):
    if isinstance(d, dict):
        yield from d.keys()
        yield from get_all_keys(list(d.values()))
    elif isinstance(d, list):
        for v in d:
            yield from get_all_keys(v)
 

с

 ret = get_all_keys(a)
list(set(ret))
 

дайте

 ['first_messanger', 'secondary_messanger', 'galaxy', 'earth_forecast', 'globe', 'forecast', 'day', 'zip_code', 'avg_temp', 'city_name', 'temp', 'earth', 'first_entry']