我有一个作为事件数据流发布的数据结构:
first = 12,
second = 20,
third = 120,
fourth = false,
fifth = "Fault"下面我有关于上面的值的警报/条件,如果警报逻辑表达式的计算结果为真,将在后端产生警报。例如:Alarm1:(first < 10 && second > 25) || (first > 7 && second <= 22)
Alarm2:fourth = true && (fifth == "Fault" || fifth == "Error")
如果我的表达式是用JavaScipt语法表达的,我如何才能以编程方式找到哪些变量的值/组合将使逻辑表达式为真。
例如: Alarm1: first = 9,second = 20将计算为true。(我想找到这些值) first =9不足以计算为true。
那么如何找到一个或多个使条件计算为真的变量值。
有没有JavaScript解析器可以帮我解决这个问题?
谢谢,Rad
发布于 2018-02-24 13:20:28
听起来像是一个简单的状态机就可以工作。
状态机知道要监视的变量名、要计算的布尔表达式以及要执行的回调。回调接收布尔表达式的结果。
当一个变量赋值表达式被添加到状态机时,该机器会检查它正在监视的所有变量是否都已累计。如果不是,机器只存储变量赋值,并等待下一个变量赋值。否则,机器使用其累积的变量赋值来计算布尔表达式。
这段ES6代码实现了这样一个状态机。它调用eval(),这打开了一个巨大的安全漏洞。因此,请小心将JavaScript输入到此代码中。
function State(
_variableNames /* array */,
_booleanExpression /* string */,
_callback /* function(boolean) -> void */)
{
/* Mapping of variable names to their local assignments.
E.g. 'first' -> 'let first = 42'
See this.addVar(). */
let _variableMap = new Map();
function haveAllValuesBeenSet()
{
return _variableNames.every(name => _variableMap.has(name));
}
function getSafeAssignment(assignment)
{
/* Turn global assignments into local assignments
by prepending 'let'. This way the assigments
won't pollute the global namespace when they're
run thru eval(). */
if (assignment.startsWith('let '))
return assignment;
else if (assignment.startsWith('var '))
return 'let ' + assignment.substring(4);
else
return 'let ' + assignment;
}
function evalExpression()
{
let assigments = '';
/* IE 11 doesn't support the Map.values property. */
for (let [_, assignment] of _variableMap)
{
assigments += assignment + ';\n';
}
let expression = assigments + _booleanExpression;
/* Uncomment to see the full expression
that's being evaluated. */
console.log(expression);
try
{
return eval(expression);
}
catch (ex)
{
console.log('ERROR in evalExpression(): ' + ex.message + '\n' + expression);
}
}
/* Add a variable assigment to the state machine,
e.g. "second = 55" */
this.addVar =
function(assignment /* string */)
{
let parts = assignment.split('=').map(s => s.trim());
let name = parts[0];
let safeAssigment = getSafeAssignment(assignment);
if (!_variableNames.includes(name))
return;
if (!_variableMap.get(name))
_variableMap.set(name, safeAssigment);
if (haveAllValuesBeenSet())
{
_callback(evalExpression());
_variableMap.clear();
}
};
}
function StateAggregator()
{
let _states = [];
this.add =
function(state)
{
_states.push(state);
};
this.applyAssignment =
function(assignment)
{
for (let state of _states)
{
state.addVar(assignment);
}
};
}
/* Create two state machines. */
var firstAndSecondState = new State(
['first', 'second'],
'(first < 10 && second > 25) || (first > 7 && second <= 22)',
function(booleanResult)
{
console.log('firstAndSecondState: ' + booleanResult);
});
var fourthAndFifthState = new State(
['fourth', 'fifth'],
'fourth === true && (fifth === "Fault" || fifth === "Error")',
function(booleanResult)
{
console.log('fourthAndFifthState: ' + booleanResult);
});
/* For convenience, a simple aggregator that allows a single variable
assigment to be broadcast to all of the state machines. */
var agg = new StateAggregator();
agg.add(firstAndSecondState);
agg.add(fourthAndFifthState);
var dataStream = [
'first = 12',
'second = 20',
'third = 120',
'fourth = false',
'fifth = "Fault"'
];
for (let assignment of dataStream)
{
agg.applyAssignment(assignment);
}
https://stackoverflow.com/questions/48956260
复制相似问题