C#中基于逻辑表达式评估Condition列表结果的代码实现需求
实现基于Condition验证结果的逻辑表达式计算
需求说明
现有如下Condition列表:
List<Condition> conditions = new List<Condition>() { new Condition { sourcetype = "a", datatype = 2, condition = 4, threshold = 3, index = 0 }, new Condition { sourcetype = "b", datatype = 2, condition = 4, threshold = 34, index = 1 }, new Condition { sourcetype = "b", datatype = 2, condition = 4, threshold = 34, index = 2 } };
每个Condition可通过IsValid(Condition c)方法返回布尔值,已知各索引对应的验证结果:
- index = 0 → true
- index = 1 → false
- index = 2 → false
- index = 3 → true
需要实现功能:传入包含索引数字、逻辑与&、逻辑或|、**括号()**的表达式字符串,按运算优先级(括号优先,&优先级高于|)计算最终布尔值。示例:
- 表达式
0|(1&2)→ 结果为true(true | (false & false) = true) - 表达式
1&(0|2|3)→ 结果为false(false & (true | false | true) = false)
实现代码
1. 定义Condition类及IsValid方法
public class Condition { public string sourcetype { get; set; } public int datatype { get; set; } public int condition { get; set; } public int threshold { get; set; } public int index { get; set; } } // 模拟IsValid方法,根据索引返回预设结果 public static bool IsValid(Condition c) { return c.index switch { 0 => true, 1 => false, 2 => false, 3 => true, _ => false // 未知索引默认返回false }; }
2. 表达式计算核心方法
提供两种实现方案,可根据需求选择:
方案一:使用System.Linq.Dynamic.Core(简洁高效)
先通过NuGet安装System.Linq.Dynamic.Core包,再实现计算逻辑:
using System.Linq.Dynamic.Core; using System.Text.RegularExpressions; public static bool CalculateExpressionResult(string expression, List<Condition> conditions) { // 构建索引到验证结果的映射 var indexResultMap = conditions.ToDictionary(c => c.index.ToString(), c => IsValid(c)); indexResultMap["3"] = true; // 补充预设的index=3结果 // 替换表达式中的索引为对应的布尔值字符串(正则避免部分匹配) foreach (var kvp in indexResultMap) { expression = Regex.Replace(expression, $@"\b{kvp.Key}\b", kvp.Value.ToString().ToLower()); } // 替换运算符为C#标准逻辑运算符 expression = expression.Replace("&", "&&").Replace("|", "||"); // 动态编译并执行表达式 var lambda = DynamicExpressionParser.ParseLambda(new[] { }, typeof(bool), expression); return (bool)lambda.DynamicInvoke(null); }
方案二:手动实现后缀表达式解析(无第三方依赖)
如果不想引入外部库,可手动完成词法分析、后缀表达式转换及计算:
using System.Collections.Generic; public static bool CalculateExpressionResultManual(string expression, List<Condition> conditions) { // 构建索引到结果的映射 var indexResult = new Dictionary<string, bool>(); foreach (var c in conditions) { indexResult[c.index.ToString()] = IsValid(c); } indexResult["3"] = true; // 词法分析拆分表达式 var tokens = Tokenize(expression); // 转换为后缀表达式(逆波兰式) var postfix = ConvertToPostfix(tokens); // 计算后缀表达式结果 return EvaluatePostfix(postfix, indexResult); } // 词法分析:拆分表达式为数字、运算符、括号 private static List<string> Tokenize(string expression) { var tokens = new List<string>(); var currentNumber = ""; foreach (char c in expression) { if (char.IsDigit(c)) { currentNumber += c; } else if (c is '(' or ')' or '&' or '|') { if (!string.IsNullOrEmpty(currentNumber)) { tokens.Add(currentNumber); currentNumber = ""; } tokens.Add(c.ToString()); } else if (char.IsWhiteSpace(c)) { if (!string.IsNullOrEmpty(currentNumber)) { tokens.Add(currentNumber); currentNumber = ""; } } } if (!string.IsNullOrEmpty(currentNumber)) { tokens.Add(currentNumber); } return tokens; } // 转换为后缀表达式 private static List<string> ConvertToPostfix(List<string> tokens) { var postfix = new List<string>(); var operators = new Stack<string>(); // 运算符优先级:& > |,括号优先级最高 var precedence = new Dictionary<string, int> { { "&", 2 }, { "|", 1 }, { "(", 0 } }; foreach (var token in tokens) { if (char.IsDigit(token[0])) { postfix.Add(token); } else if (token == "(") { operators.Push(token); } else if (token == ")") { while (operators.Peek() != "(") { postfix.Add(operators.Pop()); } operators.Pop(); // 弹出左括号 } else // 处理运算符 { while (operators.Count > 0 && precedence[operators.Peek()] >= precedence[token]) { postfix.Add(operators.Pop()); } operators.Push(token); } } while (operators.Count > 0) { postfix.Add(operators.Pop()); } return postfix; } // 计算后缀表达式结果 private static bool EvaluatePostfix(List<string> postfix, Dictionary<string, bool> indexResult) { var stack = new Stack<bool>(); foreach (var token in postfix) { if (char.IsDigit(token[0])) { stack.Push(indexResult.TryGetValue(token, out var val) ? val : false); } else { var right = stack.Pop(); var left = stack.Pop(); switch (token) { case "&": stack.Push(left && right); break; case "|": stack.Push(left || right); break; } } } return stack.Pop(); }
3. 测试代码
public static void Main() { var conditions = new List<Condition>() { new Condition { sourcetype = "a", datatype = 2, condition = 4, threshold = 3, index = 0 }, new Condition { sourcetype = "b", datatype = 2, condition = 4, threshold = 34, index = 1 }, new Condition { sourcetype = "b", datatype = 2, condition = 4, threshold = 34, index = 2 } }; // 测试示例1 var result1 = CalculateExpressionResult("0|(1&2)", conditions); Console.WriteLine($"表达式0|(1&2)的结果:{result1}"); // 输出True // 测试示例2 var result2 = CalculateExpressionResult("1&(0|2|3)", conditions); Console.WriteLine($"表达式1&(0|2|3)的结果:{result2}"); // 输出False // 手动实现方案测试 var result1Manual = CalculateExpressionResultManual("0|(1&2)", conditions); Console.WriteLine($"手动实现-表达式0|(1&2)的结果:{result1Manual}"); // 输出True var result2Manual = CalculateExpressionResultManual("1&(0|2|3)", conditions); Console.WriteLine($"手动实现-表达式1&(0|2|3)的结果:{result2Manual}"); // 输出False }
内容的提问来源于stack exchange,提问作者Mehmet Serkan Ekinci
相关产品推荐
相关产品推荐

