Поиск ключа во вложенном словаре с помощью Python - PullRequest
0 голосов
/ 24 августа 2018

Ditionary:

data = {
    "president": {
        "name": "Zaphod Beeblebrox",
        "species": "Betelgeusian"
    }
}

Что я хотел бы сделать, это вернуть, если существует ключ с именем "name".

if 'president' in data and 'name' in data['president']:
    print("found")

Это работает нормально, но только если у меня есть предварительнознание структуры словаря.Есть ли способ узнать, существует ли подраздел с именем «имя» рекурсивно?Я только нашел, как это сделать для верхнего уровня.

Ответы [ 3 ]

0 голосов
/ 24 августа 2018

Немного нетрадиционного хакерского способа было бы преобразовать ваш dict в строку, используя json.dumps.Затем вы можете искать ключ как в строке.

Например:

import json 

def find_key(d, key):
    if not isinstance(d, dict):
        return False
    else:
        return '"'+key+'": ' in json.dumps(d)

print(find_key(data, 'name'))
#True

Одно ограничение заключается в том, что это не будет работать, если вы можете иметь "name: " внутри одного из вашихзначения.

0 голосов
/ 24 августа 2018

Вы можете определить рекурсивный генератор с помощью try / except:

def recursive_keys(d):
    for k, v in d.items():
        try:
            yield from recursive_keys(v)
        except AttributeError:
            yield k

'name' in set(recursive_keys(data))  # True

Если вы предпочитаете, вы можете использовать isinstance вместо:

def recursive_keys(d):
    for k, v in d.items():
        if isinstance(v, dict):
            yield from recursive_keys(v)
        else:
            yield k

Это относительно дорого, поскольку вы сначала создаете set всех ключей, прежде чем проверять, существует ли элемент в set. Согласно комментарию @ pault, вы можете использовать:

any(x == 'name' for x in recursive_keys(data))

Для ленивого решения без генераторов см. @ решение DanielMesejo . Это может быть более эффективным, поскольку позволяет избежать дорогостоящих вызовов __next__.

0 голосов
/ 24 августа 2018

Вы можете выполнить рекурсивный поиск:

data = {
    "president": {
        "name": "Zaphod Beeblebrox",
        "species": "Betelgeusian"
    }
}

def r_find(target, key):
    if key in target:
        return True
    else:
        for k, v in target.items():
            if isinstance(v, dict):
                if r_find(v, key):
                    return True
        return False


print(r_find(data, "name"))
print(r_find(data, "species"))
print(r_find(data, "no-name"))

Вывод

True
True
False
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...