如何减少二进制/lambda表达式
本文关键字:lambda 表达式 二进制 何减少 | 更新日期: 2023-09-27 18:22:00
我有以下功能:
public double Probability(Expression<Func<double, bool>> predicate)
{
var expr = BinaryExpression.Lambda(predicate);
// Implementation
}
我这样称呼它:
Probability(x => x > 3 && x > 4 && x > 5)
当我调试代码时,我可以看到expr
如下所示:() => x => (((x > 3) AndAlso (x > 4)) AndAlso (x > 5))
我希望能够将其简化为:() => x => (x > 5))
问题:有什么可以开箱即用的东西吗?还是我必须自己实现?
奖金问题:LambdaExpression
和BinaryExpression
之间有什么区别?
我将从第二个问题开始LambdaExpression
和BinaryExpression
之间有什么区别
函数和函数中的表达式之间的相同差异
BinaryExpression是两个(二进制)节点之间的表达式
x > 5
这是GreaterThan类型的二进制表达式,其左侧是一个名为x的参数,右侧是一个值为5的常量。
Expression<Func<double, bool>> add = x => x > 5;
这是一个具有二进制表达式主体的lambda表达式。(检查附加正文)
对于你的问题,这是一个天真的解决方案。
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);
}
}