parse string with condition to boolean - c#

I am looking for a way to get a boolean value from a string.
I have a string, stored in a database, that is a condition to be tested with.
suppose the string = "[number] < 10000"
In my code I then plan to replace [number] with a actual number so the string would become "100 < 10000".
Is there a simple way to evaluate this string to a boolean.
In this case it would be False.
Another example: "[number] > 100 && [number] < 1000"
If number would be 200, the evaluation would be True.
What if I add code to this condition, like "if ([number] > 100 && [number] < 1000) { return true;} else {return false;}"
If there a simple way to get the return value from this string with code?

You can make use of DynamicExpression class, it is available in this nuget package. It can evaluate expressions on the fly.
Below is an example,
var expression = System.Linq.Dynamic.DynamicExpression.ParseLambda(
new System.Linq.Expressions.ParameterExpression[] { },
typeof(bool),
"100 > 1000",
new object[] { });
var compiledDelegate = expression.Compile();
var result = compiledDelegate.DynamicInvoke(null);
The result will be false as the provided expression "100 > 1000" is false.

If you need more control, you have to create expressions depending upon dynamic strings representing logical operations. For example, I have taken your first case of "[number]<1000" You can try below:
static void Main(string[] args)
{
string code = "[number] < 10000".Replace("[number]", "100");
string[] operands = code.Split('<');
var comparison = Expression.LessThan(
Expression.Constant(operands[0]),
Expression.Constant(operands[1]));
var lambda = Expression.Lambda<Func<bool>>(comparison).Compile();
bool result = lambda();
}
Or Alternatively you can use existing libraries or nuget packages for doing same thing in a more simpler way (under hood they do same though):
string code = "[number] < 10000".Replace("[number]", "100");
func = ExpressionParser.Compile<Func<bool>>(code);
bool result = func()
It makes use of Lambda parser as shown here

Related

how to check the if condition with string and integer

I want to get result of a value with if condition.
i have get some value in xml file.
now what I want is
if I have a variable "a" here i have assigned some values by using dataset.
and i have another variable "b" is assigned value from xml file.
for example
int a=25;
string b=">10"
now I want to check the condition if condition with out ">" because the symbol present in b variable. I dont know how to check this condition can anybody explain me how to acheive this.
I tried like this but not working
if(a+b)
You can use the DataTable.Compute-"trick" to evaulate such expressions:
int a = 25;
string b = ">10";
bool isTrue = (bool)new DataTable().Compute($"{a}{b}", null); // true
What is supported you can read at the DataColumn.Expression remarks.
if the condition is 1!=10, how to use not equal in this code .this
condition is not working what should i do.
As the documentation tells you that is not valid syntax, you have to use <> (look at operators). So a simple approach would be either to use <> in the first place or replace them:
b = b.Replace("!=", "<>");
You can have some function to remove non numeric characters:
public int Parse(string x)
{
x = Regex.Replace(x, "[^0-9.]", "");
int result = 0;
int.TryParse(x , out result);
return result;
}
If its always a number with a symbol then:
symbol = b[0];
int bval = int.Parse(b.Substring(1))
And considering your comment for comparison you can do:
if((symbol=='>'&&a>b)||
(symbol=='='&&a==b)||
(symbol=='<'&&a<b)
){
//do your magic here
}
Of course you may need only one of < = > or you may need to have separate if conditions for each, what ever suits your needs, but I just wanted to give the idea.
I tried like this
if (b.Contains(">")) {
b = b.Replace(">", "");
if (a >Convert.ToInt32(b))
{
Console.WriteLine("value is less");
}
else
{
Console.WriteLine("value is Greater");
}
}
similarly all the symbols
First separate symbol from b:
string symbol = b[0].ToString();
string numberString = b.SubString(1);
int number = int.Parse(numberString);
Now use switch to get operation for symbol and compare:
bool result = false;
switch (symbol)
{
case ">":
if (a > number)
{
result = true;
}
break;
}
EDIT: Changed symbol declaration to avoid error: "cannot implicit convert type char to string"

how to compare 2 strings in c#

I have some string like this:
str1 = STA001, str2 = STA002, str3 = STA003
and have code to compare strings:
private bool IsSubstring(string strChild, string strParent)
{
if (!strParent.Contains(strChild))
{
return false;
}
else return true;
}
If I have strChild = STA001STA002 and strParent = STA001STA002STA003 then return true but when I enter strChild = STA001STA003 and check with strParent = STA001STA002STA003 then return false although STA001STA003 have contains in strParent. How can i resolve it?
What you're describing is not a substring. It is basically asking of two collections the question "is this one a subset of the other one?" This question is far easier to ask when the collection is a set such as HashSet<T> than when the collection is a big concatenated string.
This would be a much better way to write your code:
var setOne = new HashSet<string> { "STA001", "STA003" };
var setTwo = new HashSet<string> { "STA001", "STA002", "STA003" };
Console.WriteLine(setOne.IsSubsetOf(setTwo)); // True
Console.WriteLine(setTwo.IsSubsetOf(setOne)); // False
Or, if the STA00 part was just filler to make it make sense in the context of strings, then use ints directly:
var setOne = new HashSet<int> { 1, 3 };
var setTwo = new HashSet<int> { 1, 2, 3 };
Console.WriteLine(setOne.IsSubsetOf(setTwo)); // True
Console.WriteLine(setTwo.IsSubsetOf(setOne)); // False
The Contains method only looks for an exact match, it doesn't look for parts of the string.
Divide the child string into its parts, and look for each part in the parent string:
private bool IsSubstring(string child, string parent) {
for (int i = 0; i < child.Length; i+= 6) {
if (!parent.Contains(child.Substring(i, 6))) {
return false;
}
}
return true;
}
You should however consider it cross-part matches are possible, and if that is an issue. E.g. looking for "1STA00" in "STA001STA002". If that would be a problem, then you should divide the parent string similarly, and only make direct comparisons between the parts, not using the Contains method.
Note: Using hungarian notation for the data type of variables is not encouraged in C#.
This may be a bit on the overkill side, but it might be incredibly beneficial.
private static bool ContainedWord(string input, string phrase)
{
var pattern = String.Format(#"\b({0})", phrase);
var result = Regex.Match(input, pattern);
if(string.Compare(result, phrase) == 0)
return true;
return false;
}
If the expression finds a match, then compare the result to your phrase. If they're zero, it matched. I may be misunderstanding your intent.

Solving variable value combination through Boolean expression

I do have some boolean expressions in a file as mentioned below.
((a&&b)|(c&&a)|(r&&s) && !(c)&& (f>=5)) = false
((e&&f) !(n)&& p) = false
and so on.
My task is to find all the possible boolean combinations for the variables used in the expression , that would yield an outcome mentioned at the right hand side of the expression.
I am a beginner to c# .Kindly guide me achieve this.
You can do it for a limited number of inputs, and know input values like this:
public void CalculateExpression(Expression<Func<bool, bool, int, bool>> expr){
var compiledExpr = expr.Compile();
for(var a = false; !a; !a)
for(var b = false; !b; !b)
for(var c = 0; c < 100; c)
if(compiledExpr.Invoke(a,b,c))
//Print or do whatever you want with that parameter combination
}
//Call with any of your login sentences
CalculateExpression((a,b,c) => (a|b)&&(c>5) == false);

Evaluate Conditional Expression

I have a scenario in which I am saving my "if" conditions in database as a string. For example:
String condition = "(([age] >= 28) && ([nationality] == 'US'))";
OR
String condition = "([age] >= 28)";
Now, I want to evaluate that the user has input the condition syntactically correct. These are example of incorrect syntax:
String condition = "(([age] >= 28) && ([nationality] == 'US')"; //Missed ')' bracket
String condition = "[age] >= 28)"; //Missed Opening bracket '('
Like we have in Evaluate Query Expression. Might be Expression tress can be helpful. But how? Need help in this regard.
Take a look at NCalc. It's a framework for evaluating mathematical expressions.
When the expression has a syntax error, the evaluation will throw an EvaluationException.
try
{
new Expression("(3 + 2").Evaluate();
}
catch(EvaluationException e)
{
Console.WriteLine("Error catched: " + e.Message);
}
Though, you can also detect syntax errors before the evaluation by using the HasErrors() method.
Expression e = new Expression("a + b * (");
if(e.HasErrors())
{
Console.WriteLine(e.Error);
}
Visual studio doesn't really know what the strings represent so to my knowledge there is no parsing done within the strings themselves.
Typically when programming with C# and using sql, you'd try to do as much of the calculations as possible in C# itself (if it's feasible select the whole table then deal with the result using C#).
If the database is really slow which is quite often the case, it may be useful writing a SQL Builder class to deal with the hardcoded strings.
If you use neither of these methods, unfortunately the best you can really hope for is runtime exceptions (which isn't optimal for obvious reasons).
EDIT:
It seems a SelectQueryBuilder library already exists for the second scenario I suggested.
I found this solution
evaluate an arithmetic expression stored in a string (C#)
SOLUTION:
string conditiontext = "(([age] >= 28) && ([nationality] == \"US\"))";
conditiontext = conditiontext.Replace("[age]", 32)
.Replace("[nationality]","US");
/*VsaEngine*/
var engine = Microsoft.JScript.Vsa.VsaEngine.CreateEngine();
/** Result will be either true or false based on evaluation string*/
var result = Microsoft.JScript.Eval.JScriptEvaluate(conditiontext, engine);
[Note: This interface is deprecated. But it evaluates any arithmetic expressions and c# expressions]
You could use System.Data and its DataTable.Compute() method.
Here is the code:
public bool CheckCondition()
{
// parameters
(string name, object value)[] variables =new (string name, object value)[1];
variables[0].name = "age";
variables[0].value = 28;
variables[1].name = "nationality";
variables[1].value = "US";
string conditions = "(([age] >= 28) && ([nationality] == 'US'))";
conditions.Replace("[", "").Replace("]", "").Replace("&&", "AND").Replace("||", "OR");
using DataTable table = new DataTable();
foreach (var (name, value) in variables)
table.Columns.Add(name, value is null ? typeof(object) : value.GetType());
table.Rows.Add();
foreach (var (name, value) in variables)
table.Rows[0][name] = value;
table.Columns.Add("_Result", typeof(double)).Expression = conditions
?? throw new ArgumentNullException(nameof(conditions));
return (bool)(Convert.ChangeType(table.Compute($"Min(_Result)", null), typeof(bool)));
}

Evaluate expression as string, return object?

Basically I have some code where when it happens, I need to set some object equal to some expression. All of this "what to do" jazz is stored as a string. So I parse it, and use reflection to find the object I am doing it to. Now I need to find out how to store the value to this object. The problem is the value could be "1", "1*(5/2)", or "some string value". It would be really cool if I could have expressions like "this.SomeProperty" or "(x > 3 ? 4 : 5)".
Also, the object it is storing to, could be a string, int, double, or float at the minimum.
The VS2008 samples included a nifty ExpressionParser which could be used as a generic expression parser (VS2008 Samples). With a few small updates, and a custom factory class, we can turn it into something a bit more expressive:
string expression = "(1 + 2)";
var func = FunctionFactory.Create<int>(expression);
Or:
expression = "(a * b)";
var func2 = FunctionFactory.Create<int, int, int>(expression, new[] { "a", "b" });
The return types of these Create methods are Func<> instances, which means we get nice strongly type delegates:
int result = func2(45, 100); // result = 450;
I've push the code to a gist
Update: I've recently blogged about this too.
Update 2, another example:
var person = new Person { Age = 5 };
string expression = "(Age == 5)";
var func3 = FunctionFactory.Create<Person, bool>(expression);
bool isFive = func3(person); // Should be true.
Have you seen http://ncalc.codeplex.com ?
It's extensible, fast (e.g. has its own cache) enables you to provide custom functions and varaibles at run time by handling EvaluateFunction/EvaluateParameter events. Example expressions it can parse:
Expression e = new Expression("Round(Pow(Pi, 2) + Pow([Pi2], 2) + X, 2)");
e.Parameters["Pi2"] = new Expression("Pi * Pi");
e.Parameters["X"] = 10;
e.EvaluateParameter += delegate(string name, ParameterArgs args)
{
if (name == "Pi")
args.Result = 3.14;
};
Debug.Assert(117.07 == e.Evaluate());
It also handles unicode & many data type natively. It comes with an antler file if you want to change the grammer. There is also a fork which supports MEF to load new functions.

Categories

Resources