You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 22:07:54