【问题标题】:Evaluating boolean expression in C#在 C# 中评估布尔表达式
【发布时间】:2017-12-26 07:05:34
【问题描述】:

我编写了下面的代码来评估布尔表达式。表达式以对象的形式编码。

这是我查看代码并思考的时刻之一:我确信有更好的编码方法,使用更少的布尔变量但看不到正确的方法。有什么帮助吗?已编写单元测试并通过各种输入。

if (tree == null || !tree.IsActive || tree.FilterNodes == null)
{
     return false;
}
var result = false;
foreach (var filter in tree.FilterNodes.Where(a => a.IsActive && a.ConditionNodes != null))
{
     var tempBool = false;
     foreach (var condition in filter.ConditionNodes.Where(a => a.IsActive))
     {
          if (!string.IsNullOrWhiteSpace(condition.FieldName) && values.ContainsKey(condition.FieldName))
          {
               var value = values[condition.FieldName];
               if (filter.LogicalOperator == LogicalOperator.Or && ApplyCondition(condition.ConditionOperator, value, condition.FieldValue))
               {
                   tempBool = true;
                   break;
               }
               else if (filter.LogicalOperator == LogicalOperator.And)
               {
                   tempBool = ApplyCondition(condition.ConditionOperator, value, condition.FieldValue);
                   if (!tempBool)
                   {
                        break;
                   }
               }
               else
               {
                   tempBool = false;
               }
           }
           else if (!string.IsNullOrWhiteSpace(condition.FieldName) && filter.LogicalOperator == LogicalOperator.And)
           {
                tempBool = false;
           }
     }
     result = tempBool;
     if (!result)
     {
          break;
     }
}
return result;

【问题讨论】:

  • 我知道有点晚了,但你试过Shunting yard algorithm吗?我实现了一些类似的东西,但我评估表达式字符串而不是对象。可以看看here

标签: c# boolean expression boolean-logic boolean-expression


【解决方案1】:

编写布尔解释器的更正式的方法是考虑由正式语法生成的布尔表达式并编写解析器解释器 为它。解释器可以实现为抽象语法树

我制作了一个开源库来实现这一点,如果您愿意,可以查看GitHub

【讨论】:

    【解决方案2】:

    您可以在循环中设置tempBool = false 的第一件事并省略else 和最后一个else if

     foreach (var condition in filter.ConditionNodes.Where(a => a.IsActive))
     {
          tempBool = false;
          if (!string.IsNullOrWhiteSpace(condition.FieldName) && values.ContainsKey(condition.FieldName))
          {
               var value = values[condition.FieldName];
               if (filter.LogicalOperator == LogicalOperator.Or && ApplyCondition(condition.ConditionOperator, value, condition.FieldValue))
               {
                   tempBool = true;
                   break;
               }
               else if (filter.LogicalOperator == LogicalOperator.And)
               {
                   tempBool = ApplyCondition(condition.ConditionOperator, value, condition.FieldValue);
                   if (!tempBool)
                   {
                        break;
                   }
               }
           }
     }
    

    编辑

    它变得更加简单:

     foreach (var condition in filter.ConditionNodes.Where(a => a.IsActive))
     {
          tempBool = false;
          if (!string.IsNullOrWhiteSpace(condition.FieldName) && values.ContainsKey(condition.FieldName))
          {
               var value = values[condition.FieldName];
               tempBool == ApplyCondition(condition.ConditionOperator, value, condition.FieldValue);
    
               if ((filter.LogicalOperator == LogicalOperator.And && !tempBool) || (filter.LogicalOperator == LogicalOperator.Or && tempBool))
               {
                    break;
               }
           }
     }
    

    如果您需要ApplyCondition 为真,然后将tempBool 设置为true(也是ApplyCondition 的结果)。在 else 中,如果您将 tempBool 设置为 ApplyCondition 的结果。这意味着您可以首先将tempBool 设置为ApplyCondition 的结果。现在你只需要决定是否需要中断。

    【讨论】:

    • 谢谢,但即使做了这样的改变,它仍然感觉很复杂
    • tempbool 在循环之前设置为 false。值更改的唯一一次它打破了循环。所以没有必要在循环开始时将其重置为 false。
    • @RomanoZumbé 你需要改变 || filter.LogicalOperator == LogicalOperator.Or 到 || (filter.LogicalOperator == LogicalOperator.Or && tempBool)
    • @GregTarr 完成!
    【解决方案3】:

    采用更 o-o 的方法,我认为您的运算符需要由继承自基类的类定义。基类将具有您的运算符实现的抽象 Evaluate 方法。然后,您可以使用 o-o 多态性来评估您的运算符,而不必担心内部细节。实际上,您已经开始使用简单的解释器。

    【讨论】:

      猜你喜欢
      • 2013-12-15
      • 2017-02-08
      • 1970-01-01
      • 1970-01-01
      • 2015-10-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多