首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用NCalc获取表达式中的参数

使用NCalc获取表达式中的参数
EN

Stack Overflow用户
提问于 2014-04-11 13:09:57
回答 4查看 10.2K关注 0票数 11

我有一个表达式,我想解析这个表达式,以获得所有使用参数的列表。

例如:"X +5/(Y-1)“应该给我以下结果: X,Y

我已经在我的项目中使用了NCalc;那么是否可以使用NCalc来获取表达式中使用的参数?

根据这个讨论条目(https://ncalc.codeplex.com/discussions/361959)是的,但我不太明白答案。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2014-04-11 13:38:12

来自这里的讨论/回答:http://ncalc.codeplex.com/discussions/360990

我已经测试并工作过的一个实现(针对您提供的样例表达式)是实现一个LogicalExpressionVisitor,并让它在找到参数时记录它们:

代码语言:javascript
复制
class ParameterExtractionVisitor : LogicalExpressionVisitor
{
    public HashSet<string> Parameters = new HashSet<string>();

    public override void Visit(NCalc.Domain.Identifier function)
    {
        //Parameter - add to list
        Parameters.Add(function.Name);
    }

    public override void Visit(NCalc.Domain.UnaryExpression expression)
    {
        expression.Expression.Accept(this);
    }

    public override void Visit(NCalc.Domain.BinaryExpression expression)
    {
        //Visit left and right
        expression.LeftExpression.Accept(this);
        expression.RightExpression.Accept(this);
    }

    public override void Visit(NCalc.Domain.TernaryExpression expression)
    {
        //Visit left, right and middle
        expression.LeftExpression.Accept(this);
        expression.RightExpression.Accept(this);
        expression.MiddleExpression.Accept(this);
    }

    public override void Visit(Function function)
    {
        foreach (var expression in function.Expressions)
        {
            expression.Accept(this);
        }
    }

    public override void Visit(LogicalExpression expression)
    {

    }

    public override void Visit(ValueExpression expression)
    {

    }
}

然后你会把它用作:

代码语言:javascript
复制
var expression = NCalc.Expression.Compile("2 * [x] ^ 2 + 5 * [y]", false);

ParameterExtractionVisitor visitor = new ParameterExtractionVisitor();
expression.Accept(visitor);

var extractedParameters = visitor.Parameters;

foreach (var param in extractedParameters)
    Console.WriteLine(param);

这个输出"x“和"y”给我。

注意HashSetParameterExtractionVisitor中的使用。这是因为如果表达式包含相同的变量不止一次(例如:"[x] + [x]"),它将被添加两次。如果要在每次使用相同变量时存储一个条目,请将HashSet替换为List

总之,我对NCalc的经验非常少,所以我对被覆盖的LogicalExpressionVisitor方法的实现只是猜测。当我用void Visit(ValueExpression expression)重写expression.Accept(this)方法时,它产生了一个StackOverflowException。因此,我简单地将实现保留为空白,而且它似乎起作用了。所以我建议你接受我的回答。您的里程可能不同,我不能说这是否适用于所有类型的表达式。

票数 15
EN

Stack Overflow用户

发布于 2014-10-02 20:43:50

这对我有用。你的里程可能会不同。

代码语言:javascript
复制
   public List<string> GetParameters(string expression) {
       List<string> parameters = new List<string>();
       Random random = new Random();
       NCalc.Expression e = new NCalc.Expression(expression);

       e.EvaluateFunction += delegate(string name, NCalc.FunctionArgs args) {
           args.EvaluateParameters();
           args.Result = random.Next(0, 100);
       };
       e.EvaluateParameter += delegate(string name, NCalc.ParameterArgs args) {
           parameters.Add(name);
           args.Result = random.Next(0, 100);
       };
       try {
           e.Evaluate();
           }
       catch {
            }
       return parameters;
    }

参考文献:https://ncalc.codeplex.com/discussions/79258#editor

票数 3
EN

Stack Overflow用户

发布于 2014-08-05 15:03:44

下面是我使用的另一种方法:

我构建了一个允许动态处理参数和函数的NCalc扩展方法。

代码语言:javascript
复制
internal static class NCalcExtensions
{
    public static object Evaluate(this Expression exp, EvaluateParameterHandler evaluateParameters = null, EvaluateFunctionHandler evaluateFunctions = null)
    {
        try
        {
            if (evaluateParameters != null)
                exp.EvaluateParameter += evaluateParameters;

            if (evaluateFunctions != null)
                exp.EvaluateFunction += evaluateFunctions;

            return exp.Evaluate();
        }
        finally
        {
            exp.EvaluateParameter -= evaluateParameters;
            exp.EvaluateFunction -= evaluateFunctions;
        }
    }
}

除其他外,我可以使用它来运行虚拟评估来获取参数和函数名。

代码语言:javascript
复制
var paramNames = new List<string>();
var functionNames = new List<string>();

expression.Evaluate(
    new EvaluateParameterHandler((s, a) =>
    {
        paramNames.Add(s);
        a.Result = 1; // dummy value
    }),
    new EvaluateFunctionHandler((s, a) =>
    {
        functionNames.Add(s);
        a.Result = 1; // dummy value
    }));
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23013542

复制
相关文章

相似问题

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