Рекомендации по очистке моего метода JSON "найти все вложенные" - PullRequest
0 голосов
/ 07 мая 2018

Я анализирую неизвестный вложенный объект json, заранее не знаю ни структуры, ни глубины. Я пытаюсь найти его, чтобы найти значение. Это то, что я придумал, но я нахожу это глупым. Кто-нибудь может дать мне знать, как сделать этот образ более питоническим и чище?

def find(d, key):
    if isinstance(d, dict):
        for k, v in d.iteritems():
            try:
                if key in str(v):
                    return 'found'
            except:
                continue
            if isinstance(v, dict):
                for key,value in v.iteritems():
                    try:
                        if key in str(value):
                            return "found"
                    except:
                        continue
                    if isinstance(v, dict):
                        find(v)
                    elif isinstance(v, list):
                        for x in v:
                            find(x)
    if isinstance(d, list):
        for x in d:
            try:
                if key in x:
                    return "found"
            except:
                continue
            if isinstance(v, dict):
                find(v)
            elif isinstance(v, list):
                for x in v:
                    find(x)
    else:
        if key in str(d):
            return "found"
        else:
            return "Not Found"

1 Ответ

0 голосов
/ 07 мая 2018

Как правило, более "Pythonic" использовать утки; т. е. просто попробуйте найти цель, а не isinstance. См. В чем различия между типом () и isinstance ()?

Тем не менее, ваша потребность в рекурсии требует повторного ввода значений словарей и элементов списка. (Вы также хотите найти ключи словарей?)

Оператор in может использоваться как для строк, списков, так и словарей, поэтому нет необходимости отделять словари от списков при тестировании на членство. Предполагая, что вы не хотите проверять целевой объект как подстроку, используйте isinstance(basestring) для предыдущей ссылки. Чтобы проверить, находится ли ваша цель среди значений словаря, проверьте членство в your_dictionary.values(). См. Получить ключ по значению в словаре

Поскольку значения словаря могут быть списками или словарями, я все же могу проверять словарь и типы списков, как вы, но я упоминаю, что вы можете покрывать как элементы списка, так и ключи словаря одним оператором, потому что вы спрашиваете о том, чтобы быть Pythonic. и использование перегруженного oeprator типа in для двух типов типично для Python.

Ваша идея использовать рекурсию необходима, но я бы не стал определять функцию с именем find, потому что это встроенный Python, который вы (вроде) затеняете и делаете рекурсивный вызов менее читаемым, потому что другой программист может ошибочно подумать, что вы вызываете встроенную функцию (и в качестве хорошей практики вам может потребоваться оставить обычный доступ к встроенной программе на случай, если вы захотите вызвать ее).

Чтобы проверить числовые типы, используйте `numbers.Number ', как описано в Как проверить, является ли мой объект python числом?

Также, есть решение вашей проблемы в https://gist.github.com/douglasmiranda/5127251. Я обнаружил это перед публикацией, потому что предложение регулярного выражения ColdSpeed ​​в комментарии заставило меня задуматься, не уводил ли я вас по неверному пути.

Так что-то вроде

import numbers 
def recursively_search(object_from_json, target):
    if isinstance(object_from_json, (basestring, numbers.Number)):
        return object_from_json==target # the recursion base cases
    elif isinstance(object_from_json, list):
        for element in list:
            if recursively_search(element, target):
                return True # quit at first match
    elif isinstance(object_from_json, dict):
        if target in object_from_json:
            return True # among the keys
        else:
            for value in object_from_json.values():
                if recursively_search(value, target):
                    return True # quit upon finding first match
    else:
        print ("recursively_search() did not anticipate type ",type(object_from_json))
        return False
    return False # no match found among the list elements, dict keys, nor dict values
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...