Условный рекурсивный поиск по вложенному dict по ключу и значению - PullRequest
1 голос
/ 11 апреля 2019

В терминах SQL я пытаюсь построить граф зависимостей на основе таблиц, которые используются в запросе.Мне удалось разобрать их во вложенный словарь с глубиной в соответствии с тем, как вложенные подзапросы являются и могут отличаться для каждого блока вложенного dict.Учитывая приведенный ниже пример:

sql = {"select":{"value":"some value"},
       "from":[{"value":"table1","name":"a"},
               {"value":{"select":{"value":"*"},
                         "from":{"value":"table2","name":"b"}}}]}

Ожидаемый результат:

["table1","table2"]

Мой первоначальный подход заключался в рекурсивном поиске from ключей с:

def recurd(d, find = ['from']):
    if isinstance(d, list):
        for i in d:
            yield from recurd(i)
    elif isinstance(d, dict):
        for k,v in d.items():
            if any(i in k for i in find):
                yield v
        for j in d.values():
            yield from recurd(j)

С выводом:

[{'value': 'table1', 'name': 'a'}, {'value': {'select': {'value': '*'}, 'from': {'value': 'table2', 'name': 'b'}}}]
{'value': 'table2', 'name': 'b'}

Хотя это и ожидается, я нахожу довольно запутанным также рекурсивное возвращение значений, которые я хочу, на основе ключа и значения.Я попытался осмотреться, но кажется, что большинство примеров рекурсии, примененных к вложенным диктам, смотрят только на ключи, аналогично примеру, приведенному выше.

1 Ответ

1 голос
/ 11 апреля 2019

Функция должна отслеживать родительский ключ по мере его повторения, чтобы она могла выдавать значение только в том случае, если родительский ключ равен 'from':

def get_tables(d, find=('from',), parent_key=None):
    if isinstance(d, dict):
        if parent_key in find and isinstance(d.get('value'), str):
            yield d['value']
        for k, v in d.items():
            yield from get_tables(v, find, k)
    elif isinstance(d, list):
        for i in d:
            yield from get_tables(i, find, parent_key)

, поэтому list(get_tables(sql)) возвращает:

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