I want to solve a conditional equation in iOS:
The equation I get from database is in NSString format, for example:
if((height > 0), (weight+ 2 ), ( weight-1 ) )
As per our understanding, if I parse the above string and separateheight>0
condition, it will be in the NSString
format. But to evaluate it how do I convert the string to a conditional statement?
Once the conditional statement is obtained the equation can be solved by converting it to a ternary equation as follows:
Bool status;
NSString *condition=@” height>0”;
If(condition) //But condition is treated as a string and not as a conditional statement.
{
status=True;
}
else
{
status=False;
}
Return status ? weight+ 2 : weight-1;`
Also the equations can dynamically change, so they cannot be hard coded. In short how do I solve this equation which I get as a NSString
.
Thank you for your patience!
DDMathParser author here...
To expand on Jonathan's answer, here's how you could do it entirely in DDMathParser. However, to parse the string as-is, you'll need to do two things.
First, you'll need to create an if
function:
DDMathEvaluator *evaluator = [DDMathEvaluator sharedMathEvaluator];
[evaluator registerFunction:^DDExpression *(NSArray *args, NSDictionary *vars, DDMathEvaluator *eval, NSError *__autoreleasing *error) {
if ([args count] == 3) {
DDExpression *condition = [args objectAtIndex:0];
DDExpression *resultExpression = nil;
NSNumber *conditionValue = [condition evaluateWithSubstitutions:vars evaluator:eval error:error];
if ([conditionValue boolValue] == YES) {
resultExpression = [args objectAtIndex:1];
} else {
resultExpression = [args objectAtIndex:2];
}
NSNumber *result = [resultExpression evaluateWithSubstitutions:vars evaluator:eval error:error];
return [DDExpression numberExpressionWithNumber:result];
}
return nil;
} forName:@"if"];
This creates the if()
function, which takes three parameters. Depending on how the first parameter evaluates, it either evaluates to the result of the second or third parameter.
The other thing you'll need to do is tell the evaluator what height
and weight
mean. Since they don't start with a $
character, they get interpreted as functions, and not variables. If they started with a $
, then it would be as simple as evaluating it like this:
NSString *expression = @"if(($height > 0), ($weight+ 2 ), ( $weight-1 ) )";
NSDictionary *variables = @{@"height" : @42, @"weight" : @13};
NSNumber *result = [expression evaluateWithSubstitutions:variables evaluator:evaluator error:nil];
However, since they don't start with a $
, they're functions, which means you need to tell the evaluator what the functions evaluate to. You could do this by creating functions for both height
and weight
, just like you did for if
:
[evaluator registerFunction:^DDExpression *(NSArray *args, NSDictionary *vars, DDMathEvaluator *eval, NSError **error) {
return [DDExpression numberExpressionWithNumber:@42];
} forName:@"height"];
Alternatively, you could make it a bit more dynamic and use the functionResolver
block of DDMathEvaluator
, which is a block that returns a block (woooooo) and would look like this:
NSDictionary *values = @{@"height": @42, @"weight": @13};
[evaluator setFunctionResolver:^DDMathFunction(NSString *name) {
DDMathFunction f = ^(NSArray *args, NSDictionary *vars, DDMathEvaluator *eval, NSError **error) {
NSNumber *n = [values objectForKey:name];
if (!n) { n = @0; }
return [DDExpression numberExpressionWithNumber:n];
};
return f;
}];
With those two pieces in place (registering if
and providing the values of height
and weight
), you can do:
NSString *expression = @"if((height > 0), (weight+ 2 ), ( weight-1 ) )";
NSNumber *result = [expression evaluateWithSubstitutions:nil evaluator:evaluator error:nil];
... and get back the proper result of @15
.
(I have plans to make DDMathParser
allow unknown functions to fall back to provided variable values, but I haven't quite finished it yet)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With