【问题标题】:How to reduce a binary/lambda expression? [closed]如何减少二进制/ lambda 表达式? [关闭]
【发布时间】:2015-11-13 20:10:45
【问题描述】:

我有以下功能:

public double Probability(Expression<Func<double, bool>> predicate)
{
    var expr = BinaryExpression.Lambda(predicate);  
    // Implementation
}

我这样称呼:

Probability(x => x > 3 && x > 4 && x > 5)

当我调试我的代码时,我可以看到 expr 看起来像这样: () =&gt; x =&gt; (((x &gt; 3) AndAlso (x &gt; 4)) AndAlso (x &gt; 5))

我希望能够将其减少为:() =&gt; x =&gt; (x &gt; 5))

问题:有什么东西可以开箱即用,还是我必须自己实现?

额外问题LambdaExpressionBinaryExpression 有什么区别?

【问题讨论】:

  • 你的意思是除了把你的电话改成Probability(x =&gt; x &gt; 5);吗? ;)
  • 我不希望找到能做到这一点的东西,它本质上是优化编译器的(一个简单的)部分。重新奖励:LambdaExpression 表示您可以调用的方法——它有一个参数列表和一个主体。 BinaryExpression 只代表一个二进制操作——没有上下文,没有参数列表,你不能编译和调用它。
  • stackoverflow.com/questions/1101841/… 看看@JonSkeet 的 MaxBy() 扩展方法实现
  • 我希望能够对其调用 Reduce(),但 BinaryExpression 上的 Reduce 没有任何作用。文档也不是很复杂...:-P
  • Reduce 与“扩展”表达式有关。请参阅 herehere。基本上,扩展表达式是不属于 CLR 的表达式,它们是您正在做的任何其他事情的自定义。它们通常可以“简化”为 CLR 表达式。

标签: c# .net lambda expression-trees


【解决方案1】:

我将从第二个问题开始。
LambdaExpressionBinaryExpression 有什么区别?
函数与函数内的表达式的区别相同。
BinaryExpression 是两个(二进制)节点之间的表达式

x > 5 

这是一个 GreaterThan 类型的二进制表达式,它的左边是一个名为 x 的参数,它的右边是一个值为 5 的常数。

Expression<Func<double, bool>> add = x => x > 5;

这是一个具有二进制表达式主体的 lambda 表达式。 (检查add.Body)

对于您的问题,这是一个幼稚的解决方案。

class Program
{
    static void Main(string[] args) {
        Expression<Func<double, bool>> predicate = x => x > 3 && x > 4;
        var visitor = new BinaryExpressionVisitor();
        predicate = (Expression<Func<double, bool>>)visitor.Visit(predicate);
    }
}

public class BinaryExpressionVisitor : ExpressionVisitor
{
    private bool root = true;
    private List<ConstantExpression> constants = new List<ConstantExpression>();
    private List<BinaryExpression> binaryExpressions = new List<BinaryExpression>();
    private HashSet<ParameterExpression> @params = new HashSet<ParameterExpression>();

    protected override Expression VisitBinary(BinaryExpression node) {
        if (IsSimpleBinaryExpression(node)) {
            binaryExpressions.Add(node);
        }
        else if (node.NodeType != ExpressionType.AndAlso) {
            return node;
        }

        if (root) {
            root = false;
            Visit(node.Right);
            Visit(node.Left);

            if (@params.Count == 1) {
                var @param = @params.ElementAt(0);
                var hashSet = new HashSet<ExpressionType>(binaryExpressions.Select(be => be.NodeType));

                if (hashSet.Count == 1) {
                    var binaryExpression = binaryExpressions[0];
                    var nodeType = binaryExpression.NodeType;
                    var constant = GetConstantByNodeType(nodeType);

                    return Expression.MakeBinary(nodeType, @param, constant);
                }
            }
        }

        return base.VisitBinary(node);
    }

    protected override Expression VisitConstant(ConstantExpression node) {
        constants.Add(node);

        return base.VisitConstant(node);
    }

    protected override Expression VisitParameter(ParameterExpression node) {
        @params.Add(node);

        return base.VisitParameter(node);
    }

    private bool IsSimpleBinaryExpression(Expression node) {
        return node.NodeType == ExpressionType.GreaterThan || node.NodeType == ExpressionType.LessThan;
    }

    private ConstantExpression GetConstantByNodeType(ExpressionType expressionType) {
        var values = constants.Select(c => c.Value);
        var value = expressionType == ExpressionType.GreaterThan ? values.Max() : values.Min();

        return Expression.Constant(value);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-14
    相关资源
    最近更新 更多