Дерево Json — вычисление выражения

#python #json #algorithm #data-structures #tree

#python #json #алгоритм #структуры данных #дерево

Вопрос:

У меня есть json, представляющий математическое выражение в приведенном ниже формате, и мне нужно оценить то же самое.

 {
        "operator":" ",
        "params": ["60" , {
            "operator":"/",
            "params":[
                "alias3",
                {
                    "operator":" ",
                    "params":["alias1","alias2"]
                }
            ]
        }]
    }
  

Пример приведенной выше структуры будет выглядеть следующим образом:

 {
        "operator":"abs",
        "params": [
            {
                "operator":"/",
                "params":[
                    {
                        "operator": "*",
                        "params": 
                        [
                            "100",
                            {
                                "operator": "/",
                                "params": ["2000", "40"]
                            }
                        ]
                    },
                    {
                        "operator":" ",
                        "params":[
                            "30",
                            {
                                "operator": "*",
                                "params": [
                                    "25",
                                    {
                                        "operator": "-",
                                        "params": ["60", "15"]
                                    }
                                ]
                            }
                        ]
                    }
                ]
            }
        ]
    }
  

Примечание:

  • Используемые операторы , -, *, /, abs
  • Каждый оператор имеет ровно 2 параметра, кроме abs()
  • на любом заданном уровне может присутствовать любой из вышеперечисленных операторов.

приведенный выше json является представлением abs((100*(2000/40))/(30 (25*(60-15)))) и оценивается как 4.329

Пожалуйста, помогите мне оценить это дерево выражений json.

Решение, которое я нашел: эта проблема почти аналогична оценке дерева выражений. Но ввод осуществляется в формате json. Здесь я изо всех сил пытаюсь прочитать данные json. Псевдокод, подобный приведенному ниже, когда ввод осуществляется в формате дерева (с использованием узлов) — это будет рекурсивная функция.

 Let t be the syntax tree
If  t is not null then
      If t.info is operand then  
         Return  t.info
      Else
         A = solve(t.left)
         B = solve(t.right)
         return A operator B
         where operator is the info contained in t
  

Я попытался использовать тот же псевдокод и прочитать ввод из json.
Но я не могу найти правильный корневой и конечный регистр для выхода из рекурсивной функции.
Глядя на json, можно отметить одну вещь: регистр листа будет «строкой», а не-лист будет «словарем». Но проблема в том, что «operator» также является строкой, а operator никогда не будет листом. Любая помощь или предложения будут высоко оценены. Заранее спасибо.

Ответ №1:

Вы можете проверить type лист, чтобы определить, нужно ли вам анализировать его с плавающей точкой или это dict и, следовательно, использовать рекурсию.

Вы можете использовать некоторые if on operator для определения применяемой операции with. (здесь я использую пакет operator, чтобы избежать некоторых ifs)

 import operator
json_operations = {
        "operator":"abs",
        "params": [
            {
                "operator":"/",
                "params":[
                    {
                        "operator": "*",
                        "params":
                        [
                            "100",
                            {
                                "operator": "/",
                                "params": ["2000", "40"]
                            }
                        ]
                    },
                    {
                        "operator":" ",
                        "params":[
                            "30",
                            {
                                "operator": "*",
                                "params": [
                                    "25",
                                    {
                                        "operator": "-",
                                        "params": ["60", "15"]
                                    }
                                ]
                            }
                        ]
                    }
                ]
            }
        ]
}

operators = {" ": operator.add,
             "-": operator.sub,
             "*": operator.mul,
             "/": operator.truediv
             }

def do_params(p):
    if type(p) is str:
        return float(p)
    else:
        return do_operations(p)

def do_operations(p):

    if "operator" in p:
        params_1 = do_params(p["params"][0])
        if len(p["params"]) > 1:
            params_2 = do_params(p["params"][1])

        if p["operator"] == "abs":
            return abs(params_1)
        else:
            return operators[p["operator"]](params_1, params_2)

    return 0
res = do_operations(json_operations)

output : 
4.329004329004329
  

Ответ №2:

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

 from operator import add, sub, mul, truediv

def solve(tree):
    if type(tree) is not dict:
        return float(tree)  # convert string to float
    return {
        " ": add,
        "-": sub,
        "*": mul,
        "/": truediv,
        "abs": abs
    }[tree["operator"]](*map(solve, tree["params"]))
  

Словарный литерал позволяет преобразовывать имя оператора в фактическую операторную функцию, а оператор splash обеспечивает одинаково хорошую работу с унарными и двоичными операторами, предоставляя все «решаемые» параметры (1 или 2) динамически извлекаемой функции.