我有一个dict结构,如下所示:
{
"condition": "AND",
"rules": [
{
"id": "monitor_category",
"field": "monitor_category",
"type": "string",
"input": "select",
"operator": "equal",
"value": "Competition",
"decision": True
},
{
"id": "monitor_tag",
"field": "monitor_tag",
"type": "string",
"input": "text",
"operator": "equal",
"value": "PassiveTotal",
"decision": True
},
{
"condition": "OR",
"rules": [
{
"id": "article_tag",
"field": "article_tag",
"type": "string",
"input": "text",
"operator": "contains",
"value": "Attack",
"decision": False
},
{
"id": "article_tag",
"field": "article_tag",
"type": "string",
"input": "text",
"operator": "contains",
"value": "Hunt",
"decision": True
},
{
"id": "article_tag",
"field": "article_tag",
"type": "string",
"input": "text",
"operator": "contains",
"value": "Threat",
"decision": False
}
]
},
{
"id": "monitor_tag",
"field": "monitor_tag",
"type": "string",
"input": "text",
"operator": "equal",
"value": "Analysis",
"decision": False
}
]
}
对于每条规则,我都会得出一个决定并将其附加到策略规则中。我通过dict的简单递归遍历来做到这一点。在上面的示例策略中,布尔逻辑等同于:
(True and True and (False or True or False) and False)
我想拥有一个接受此策略的函数,并且能够派生布尔逻辑以返回最终评估。我知道深度搜索第一种方法可能是这里的方向,但我正在努力维护布尔状态并知道我在结构中的哪个级别。
答案 0 :(得分:1)
创建一个字典以容纳functions that correspond to 'conditions'
import operator, functools
operations = {'AND':operator.and_, 'OR':operator.or_, 'XOR':operator.xor}
编写递归函数,当'conditions'
是规则中的键时将递归,否则迭代规则并在列表中累积'decisions'
。使用functools.reduce
将condition
应用于决策。
def f(d):
func = operations.get(d['condition'], None)
if func is None:
return
decisions = []
for rule in d['rules']:
if 'condition' in rule:
decision = f(rule)
else:
decision = rule['decision']
decisions.append(decision)
return functools.reduce(func, decisions)
if func is None: return
本来是基本情况,但我不太确定它是否需要 - 如果发生这种情况,dict会搞砸,它可能会引发ValueError
我认为这是隐含的基本情况(如果有这样的事情) - 它依赖for rule in d['rules']:
循环来用完项目。
如果条件仅限于“与”和“或”,您可以使用all
和any
。
ops = {'AND':all, 'OR':any}
def g(d):
func = ops.get(d['condition'], None)
if func is None:
return
decisions = []
for rule in d['rules']:
if 'condition' in rule:
decision = f(rule)
else:
decision = rule['decision']
decisions.append(decision)
return func(decisions)