首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在JavaScript逻辑表达式中查找使表达式求值为true的变量值

在JavaScript逻辑表达式中查找使表达式求值为true的变量值
EN

Stack Overflow用户
提问于 2018-02-24 05:10:17
回答 1查看 52关注 0票数 1

我有一个作为事件数据流发布的数据结构:

代码语言:javascript
运行
复制
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

EN

回答 1

Stack Overflow用户

发布于 2018-02-24 13:20:28

听起来像是一个简单的状态机就可以工作。

状态机知道要监视的变量名、要计算的布尔表达式以及要执行的回调。回调接收布尔表达式的结果。

当一个变量赋值表达式被添加到状态机时,该机器会检查它正在监视的所有变量是否都已累计。如果不是,机器只存储变量赋值,并等待下一个变量赋值。否则,机器使用其累积的变量赋值来计算布尔表达式。

这段ES6代码实现了这样一个状态机。它调用eval(),这打开了一个巨大的安全漏洞。因此,请小心将JavaScript输入到此代码中。

代码语言: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);
}

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48956260

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档