I'm looking for a way of parsing a conditional expression to a string.
The best example I can think of is LINQ-to-SQL. It uses ExpressionVisitors to format "Where" clauses. Example:
from a in b where a.x == 5 && a.y < 3 select a
That would translate into the following string (approximately, MSSQL is not current for me):
"SELECT * FROM b WHERE x = 5 AND y < 3"
From what I've read, this was done using the ExpressionVisitor class, as explained in this article: Link
Now the problem is that I don't use LINQ, but I need this particular functionality. Is there a way of parsing a condition like that? I'm willing to do anything with reflection, delegates, lambda, etc.
Honestly, I don't think it's possible, but my brain is a bit fried (read: be nice if the question is ridiculous), so I figured I might just as well give S/O a try.
EDIT: Final usage example:
// Usage:
foo.Bar(foo => foo.X == 5 && foo.Y < 3)
// Ideal string output (variable name (foo) is not needed):
"foo.X == 5 && foo.Y < 3"
EDIT 2: Yes, a number can be lower than 3 and equal to 5. Told you my brain is fried.
If it is about about building the expression tree itself, then you could leverage C# compiler abilities.
It is legal to pass a lambda expression to a function acception an Expression>, as long as type arguments of Func are known. For example
private static void PrintExpression(Expression<Func<int, bool>> lambda)
{
Console.WriteLine(lambda.ToString());
}
can be called as
PrintExpression(a=> a > 0 && a < 5);
You can improvise with generics as
private static void PrintExpression<T1,T2>(Expression<Func<T1, T2>> lambda)
{
Console.WriteLine(lambda.ToString());
}
and calling it with
PrintExpression<int, bool>(a=> a > 0 && a < 5);
For custom printing of the expression part, you can write a simple recursive function that prints an expression or any other logic that suits you.
Remember, the lambda expression is compiled into an Expression at compile time - so can't subsititute it with already compiled Func.
As an alternative to this, you can always build a custom query provider, but that would be slightly deviating from the purpose - as you'd need to bind it some sort of queryable (custom again).
Try something like this:
static string GetExpressionString<T>(Expression<Func<T, bool>> expression)
{
return expression.Body.ToString();
}
Usage as so:
string s = GetExpressionString<Foo>(foo => foo.X == 5 && foo.Y < 3);
Which will return:
((foo.X = 5) && (foo.Y < 3))
Related
This question already has answers here:
Is there a string math evaluator in .NET?
(18 answers)
Closed 3 years ago.
Is there an easy way to parse a simple math expression represented as a string such as (x+(2*x)/(1-x)), provide a value for x, and get a result?
I looked at the VSAEngine per several online examples, however, I am getting a warning that this assembly has been deprecated and not to use it.
If it makes any differences, I am using .NET 4.0.
I urge caution against choosing an existing generic expression evaluator over a purpose-built math evaluator. The reason for this is expression evaluators are not limited to math. A clever individual could use this to create an instance of any type in the framework and call any method on the type, and that would allow him to do some decidedly unwelcome things. For example: new System.Net.WebClient().DownloadFile("illegalchildpornurl", "C:\openme.gif") will evaluate just fine in most of those, and do just what it sounds like it would (and make you a felon at the same time).
This doesn't mean don't look for something that's already written; it just means be careful. You want one that does math, and only math. Most of what's already out there isn't that picky.
I was recently using mXparser, which is a math parser library. It gives you a lot of flexibility, such as variables, functions, constants, operators. You will find below a few usage examples:
Example 1 - simple formula
Expression e = new Expression("1 + pi");
double v = e.calculate();
Example 2 - formula with variables, functions, etc.
Argument x = new Argument("x = 2");
Constant a = new Constant("a = sin(10)");
Function f = new Function("f(t) = t^2");
Expression e = new Expression("2*x + a - f(10)", x, a, f);
double v = e.calculate();
https://mxparser.codeplex.com/
https://mathparser.org/
Found recntly - you can try the syntax (and see the use case) via the Scalar Calculator app that is powered by mXparser.
Best regards
You can try using DataTable.Compute.
A related one is DataColumn.Expression.
Also check out: Doing math in vb.net like Eval in javascript
Note: I haven't used these myself.
I would also have a look at Jace (https://github.com/pieterderycke/Jace). Jace is a high performance math parser and calculation engine that supports all the .NET flavors (.NET 4.x, Windows Phone, Windows Store, ...). Jace is also available through NuGet: https://www.nuget.org/packages/Jace
Here is one way to do it. This code is written in Java. Note it does not handle negative numbers right now, but you can add that.
public class ExpressionParser {
public double eval(String exp, Map<String, Double> vars){
int bracketCounter = 0;
int operatorIndex = -1;
for(int i=0; i<exp.length(); i++){
char c = exp.charAt(i);
if(c == '(') bracketCounter++;
else if(c == ')') bracketCounter--;
else if((c == '+' || c == '-') && bracketCounter == 0){
operatorIndex = i;
break;
}
else if((c == '*' || c == '/') && bracketCounter == 0 && operatorIndex < 0){
operatorIndex = i;
}
}
if(operatorIndex < 0){
exp = exp.trim();
if(exp.charAt(0) == '(' && exp.charAt(exp.length()-1) == ')')
return eval(exp.substring(1, exp.length()-1), vars);
else if(vars.containsKey(exp))
return vars.get(exp);
else
return Double.parseDouble(exp);
}
else{
switch(exp.charAt(operatorIndex)){
case '+':
return eval(exp.substring(0, operatorIndex), vars) + eval(exp.substring(operatorIndex+1), vars);
case '-':
return eval(exp.substring(0, operatorIndex), vars) - eval(exp.substring(operatorIndex+1), vars);
case '*':
return eval(exp.substring(0, operatorIndex), vars) * eval(exp.substring(operatorIndex+1), vars);
case '/':
return eval(exp.substring(0, operatorIndex), vars) / eval(exp.substring(operatorIndex+1), vars);
}
}
return 0;
}
}
You need to import java.util.Map.
Here is how I use this code:
ExpressionParser p = new ExpressionParser();
Map vars = new HashMap<String, Double>();
vars.put("x", 2.50);
System.out.println(p.eval(" 5 + 6 * x - 1", vars));
Another option you may want to look into is the Spring.NET Framework's expression evaluation functionality. It can do a lot more than math, too.
However, the entire Spring.NET Framework might be a bit of overkill for your needs if you don't require the rest of the functionality.
Related: Equation expression parser with precedence.
As I answered in this thread (Best Free C# Math Parser using variables, user defined functions, custom operators), you can use Mathos Parser, which you can simply paste into your source code.
Mathos.Parser.MathParser parser = new Mathos.Parser.MathParser();
string expr = "(x+(2*x)/(1-x))"; // the expression
decimal result = 0; // the storage of the result
parser.LocalVariables.Add("x", 41); // 41 is the value of x
result = parser.Parse(expr); // parsing
Console.WriteLine(result); // 38.95
I recomend you to use MEEL for this.
// parse string to IExpression (symbolic type)
IExpression expression = BaseExpression.Parse("(x+(2*x)/(1-x))");
// create your own collection for attributes
var attributes = new MathAttributeCollection();
// create local variable named "x" with value 5
var attributeX = new ScalarAttrInt("x") {Value = new ScalarConstInt(5)};
attributes.Add(attributeX);
// execute math expression where x=5
var result = expression.Execute(attributes);
MessageBox.Show(result.GetText());
// result: 2.5
I have a a line of code that looks like this
var results = DataBase.Find(x.ImportanceFactor > 5 && x.ImportanceFactor < 10);
Now in the Findfunction, what Data Structure can i use?
public static int Find(??? input)
{
:
Some Code
:
}
The format needs to be exactly how i specified above, but i have having a hard time finding a data structure to support it. I have tried a number of Expressions in Linq to no success.
EDIT For Clarification:
The Find function will go into the a database and look for an object whose importance is within the specified range, and return whichever object in that range has the highest Size value. Again, that first line cant be changed in any way, regardless of what happens in the Find function. The line below needs to be available in the Find
x.ImportanceFactor > 5 && x.ImportanceFactor < 10
EDIT2:
X is a dynamic expression, not an object with properties.
This:
x.ImportanceFactor > 5 && x.ImportanceFactor < 10
is just a bool:
public static int Find(bool input)
But given the usage of x in that condition, I suspect you actually meant this:
var results = DataBase.Find(x => x.ImportanceFactor > 5 && x.ImportanceFactor < 10);
In which case you're looking at something structurally very similar to methods like Any() or Where() on IEnumerable<T>. That would use something more like Func<T, bool>:
public static int Find<T>(Func<T, bool> input)
I'm getting this error message during runtime
LINQ to Entities does not recognize the method 'Int64 Max(Int64, Int64)' method, and this method cannot be translated into a store expression.
when I try to do this:
return _dbContext.Appointment.Where(x => Math.Max(x.Appointment.StartTime.Ticks, startTime.Ticks) <= Math.Min(x.Appointment.EndTime.Ticks, endTime.Ticks));
The idea behind this query is that "if the latest start time is before the earliest end time, then you have some overlap/touching" in date and time.
Is there any way to get this line working? I already checked if EntityFunctions has 'something', which wasn't the case.
Max and Min can be implemented like this:
public static long Max(long a, long b)
{
return a < b ? b : a;
}
public static long Min(long a, long b)
{
return a < b ? a : b;
}
Since LINQ to Entities understands ? :, you will be able to inline these into your expression. Also, since Ticks is not supported, but DateTime comparison is...
Math.Max(x.Appointment.StartTime.Ticks, startTime.Ticks)
Becomes
(x.Appointment.StartTime < startTime ? startTime : x.Appointment.StartTime)
You must always keep in mind that every IQueryable provider is implemented in its own way. That query would work in Linq to Objects (as it does not gets translated to anything) but may or may not work in IQueryable providers.
In your specific case, it's telling you that it has no idea on how to translate Math.Max and Math.Min into SQL commands. And that's perfectly correct, since EF doesn't recognize those methods.
In my opinion the easiest way to accomplish what you need is reading the max and the min value with two different queries and then do your logic in plain c#. Something like this:
var min = mycontext.MyDbSet.Min(c => c.Field);
var max = mycontext.MyDbSet.Max(c => c.Field);
if (max <= min)
{
// do something
}
Is there a way a comparison in a string value can return a Boolean value. Example.
If (5 > 5000) would obviously return a false value. But what i wanted to do is have the "5 > 5000" return a false value.
Example.
string com = "5 > 10";
so is there a way to make this com variable return a false value as if it was a comparison between integers.
No built-in way but NCalc can help here
NCalc.Expression expr = new NCalc.Expression("5>10");
bool b = (bool)expr.Evaluate();
You can even use parameters
NCalc.Expression expr = new NCalc.Expression("a<b");
expr.EvaluateParameter += (name, args) =>
{
if (name == "a") args.Result = 5;
if (name == "b") args.Result = 10;
};
bool b = (bool)expr.Evaluate();
There is no built-in way to do this.
Although there are a couple of ways to approach this, one is to simply parse the text yourself. I did this in the code presented in the article A C# Expression Evaluator. You might want to review that code.
No, this can't be done directly.
You should write your own class or extend the String class. For handling a string such as "5 < 10", you need your own method.
You should search the string for signs that indicate comparison, such as "<", "==" etc, then split it and perform the comparison.
Basically: doing it yourself is the only way, but you can try to do it in an elegant way.
Short answer: no.
Long answer: feel free to parse the string yourself, looking for > < and =. Split by whitespace, parse ints then evaluate. It might get harder if you want it to work with parentheses as well...
Not directly, per se (short of the unsafe Javascript eval-execute-my-data hack) but you can try parsing it yourself, depending on how complicated of an expression you want to accept. For example, this should work with the string you have:
var arr = com.Split('>').Select(x=>int.Parse(x.Trim())).ToArray();
return arr[0] > arr[1];
You can also use regular expressions to get more complicated (untested, but it ought to work):
var r = new Regex(#"(\d+)\b*(<|>|=|<=|>=)\b*(\d+)")
var match = r.Match(com);
if(match.Success)
{
var a = int.Parse(match.Captures[0]);
var b = int.Parse(match.Captures[2]);
switch(match.Captures[1])
{
case "<":
return a < b;
case "=":
return a = b;
case ">":
return a > b;
case "<=":
return a <= b;
case "<=":
return a >= b;
}
}
//uh-oh
throw new ArgumentException("com");
Consider using FLEE:
Flee is an expression parser and evaluator for the .NET framework. It allows you to compute the value of string expressions such as sqrt(a^2 + b^2) at runtime. It uses a custom compiler, strongly-typed expression language, and lightweight codegen to compile expressions directly to IL. This means that expression evaluation is extremely fast and efficient. Try out the demo, which lets you generate images based on expressions, and see for yourself.
With FLEE you can easily accomplish this using something like:
var con = new ExpressionContext();
const string com = #"5 > 5000";
var comparison = con.CompileDynamic(com);
var result = comparison.Evaluate();
MessageBox.Show(result.ToString());
HTH...
I've been working with expression trees for a few days now and I'm curious to know what Expression.Reduce() does. The msdn documentation is not very helpful as it only states that it "reduces" the expression. Just in case, I tried an example (see below) to check if this method included mathematical reduction, but this doesn't seem to be the case.
Does anyone know what this method does and is it possible to provide a quick example showing it in action? Any good resources out there?
static void Main(string[] args)
{
Expression<Func<double, double>> func = x => (x + x + x) + Math.Exp(x + x + x);
Console.WriteLine(func);
Expression r_func = func.Reduce();
Console.WriteLine(r_func); // This prints out the same as Console.WriteLine(func)
}
The document you need to look at is expr-tree-spec.pdf.
This is the specification for the expression trees. Read the "2.2 Reducible Nodes" and "4.3.5 Reduce Method" sections.
Basically, this method is intended for people implementing or porting their dynamic langauges to .NET. So that they can create their own nodes that can "reduce" to standard expression tree nodes and can be compiled. There are some "reducible" nodes in the expression trees API, but I don't know whether you can get any practical examples (since all standard expression nodes compile anyway, as the end-user you probably do not care whether they are "reduced" behind the scenes or not).
Yes, MSDN documentation is very basic in this area, because the main source of info and docs for language implementers is on GitHub, with the documentation in its own subfolder.
With a little disassembling, I found that Expression.CanReduce always reutrns false and Expression.Reduce() always returns this. However, there are a few types that override both. LambdaExpression inherits the default implementations, which explains why the expressions that have been tried so far do not work.
One of the types that overrides Reduce() is MemberInitExpression, which led me to the following successful experiment:
class ReduceFinder : ExpressionVisitor {
public override Expression Visit(Expression node) {
if (node != null && node.CanReduce) {
var reduced = node.Reduce();
Console.WriteLine("Found expression to reduce!");
Console.WriteLine("Before: {0}: {1}", node.GetType().Name, node);
Console.WriteLine("After: {0}: {1}", reduced.GetType().Name, reduced);
}
return base.Visit(node);
}
}
class Foo {
public int x;
public int y;
}
static class Program {
static void Main() {
Expression<Func<int, Foo>> expr = z => new Foo { x = (z + 1), y = (z + 1) };
new ReduceFinder().Visit(expr);
}
}
Output:
Found expression to reduce!
Before: MemberInitExpression: new Foo() {x = (z + 1), y = (z + 1)}
After: ScopeN: { ... }
This is a fairly old question but it seems to have a bit of interest, so I'm adding this extra response with information on what the out-of-box .NET stuff does as of right now.
As far as I can tell, Reduce() is only overridden in complex operations that implement an assignment as part of their work. There seem to be three key scenarios.
Compound assignments are expanded to discrete binary arithmetic and assignment operations; in other words,
x += y
becomes
x = x + y.
Pre-increment and post-increment operators are expanded to their discrete operations. For pre-increment/decrements,
++x
becomes approximately:
x = x + 1
and
x++
becomes approximately:
temp = x;
x = x + 1;
temp;
I say approximately because the operation is not implemented as a binary operation x + 1 with the left operand being x and the right operand being the constant 1 but as a unary increment/decrement operation. The net effect is the same.
Member and list initializers are expanded from their short form to their long form. So:
new Thing() { Param1 = 4, Param2 = 5 }
becomes:
temp = new Thing();
temp.Param1 = 4;
temp.Param2 = 5;
temp;
and:
new List<int>() { 4, 5 }
becomes:
temp = new List<int>();
temp.Add(4);
temp.Add(5);
temp;
Whether these changes make it easier or harder for a person to implement something that parses an expression tree is a matter of opinion, but bottom line is that's the level of reduction that seems to come out-of-box in the .NET framework.
Further to the answer by Nick Guerrera, I have found the following expressions that have overridden the CanReduce method:
AssignBinaryExpression*
BinaryExpression
CoalesceConversionBinaryExpression*
LogicalBinaryExpression*
SimpleBinaryExpression*
ListInitExpression
MemberInitExpression
UnaryExpression
* Denotes an internal derived type of BinaryExpression according to JustDecompile
im guessing its more for different linq providers to use those to transform certain node types into a simpler ast representation.
since the docs are scant, could be used for common subexpression elimination to eliminate redundant expressions. if your function computed x+x more than once without changing local x, you could simplify it by saving the result of the first expression into a temporary. maybe it would be up to the linq provider to optionally implement these transformations.
or if you had nested BlockExpressions that contained no code ( an expression like {{{}}} ), those could be eliminated, or an empty ConditionalExpression...