#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) динамически извлекаемой функции.