2017-07-20 58 views
0

我已經編寫了下面的代碼來評估布爾表達式。表達式以對象的形式進行編碼。在C中評估布爾表達式

這是我查看代碼並思考的那些時刻之一:我確信有更好的代碼編寫方式,使用較少的布爾變量但看不到正確的路。任何幫助?單元測試已經寫好,並且正在通過各種輸入。

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; 

回答

3

您可以設置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爲true,然後將tempBool設置爲true(也是ApplyCondition的結果)。在其他情況下,如果您將tempBool設置爲ApplyCondition的結果。這意味着您可以首先將tempBool設置爲ApplyCondition的結果。現在你只需要決定是否需要休息。

+0

謝謝,但即使這種改變仍然感覺複雜 –

+0

tempbool在循環之前設置爲false。值改變的唯一時間就是跳出循環。所以在循環開始時不需要將它重置爲false。 – waltsj19

+1

看到我的編輯更簡單的解決方案 –

1

採取更多的o-o方式,我認爲您的操作符需要由繼承自基類的類來定義。基類將有一個抽象的Evaluate方法,您的操作員可以執行該方法。然後,您可以使用o-o多態性來評估您的操作員,而不用擔心內部細節。實際上,你有一個簡單的解釋器的開始。

0

更正式的方式來編碼的布爾解釋正在考慮一個布爾表達式由形式文法作爲生成並寫入解析器和用於它的一個解釋。解釋器可以實現爲抽象語法樹

我做了一個開源的庫來實現這個,如果你想要的話可​​以看看GitHub