Reputation: 5644
I am using DDMathParser
to parse formulas and calculate the results, which works great.
Question:
Is it possible to set variables to default values in case they do not exist in the substitution dictionary?
Example:
My formula $a + $b
requires two variables $a
and $b
. However, my substitution dictionary contains only an value for variable key a
(e.g. 1), but does not contain an key b
.
What would be the preferred way to define variable b
to be 0
as default value and avoid the parsing error message "unable to resolve variable"
?
Thank you!
The way I am using DDMathParser
is by looping over multiple formulas and providing the same variable substitution dictionary to each formula. Sometimes, I don't have values for the variables: In this case the variables (keys and values) would not be included in the dictionary.
Depending on the formula itself, I would like to return nil
as result for the formula if one of the variables does not exist (e.g. I don't have a value for profit
and the formula is $profit / $revenue
, I would like to return nil
which I can convert to a NSString
of n/a
later) or set the variable to 0
if it is does not exist in the dictionary (e.g. for a formula like $profitA + $profitB + $profitC
, I would like to assume 0
for any missing variables ($profitA
, $profitB
or $profitC
).
For this reason, I cannot use a generic solution, which always returns 0
or nil
, but would need to put this logic in the formula (e.g. as a custom function).
Upvotes: 2
Views: 306
Reputation: 243156
DDMathParser author here.
Is it possible to set variables to default values in case they do not exist in the substitution dictionary?
Kind of. You could do it by supplying a variableResolver
block to the math evaluator:
DDMathEvaluator *evaluator = [DDMathEvaluator sharedMathEvaluator];
[evaluator setVariableResolver:^(NSString *variable) { return @0; }];
NSNumber *n = [evaluator evaluateString:myString withSubstitutions:mySubstitutions];
The variable resolver block gets executed whenever the evaluator comes across a variable that it can't find in the substitutions dictionary.
Would it be feasible to add a custom function to DDMathParser like defaultZero($b) which retrieves the variable b if it exists or zero if not?
Hm, clever idea. You could, but you would essentially by mimicking the behavior of the variableResolver block. You'd create a new DDMathFunction
block and use the -[DDMathEvaluator registerFunction:forName:]
to tell the evaluator about it.
However, I'd recommend just supplying a variable resolver block. It'd be much simpler.
Here's how you'd define a defaultZero
function that returns either the value of the argument or 0
(if the argument can't be evaluated):
DMathEvaluator *evaluator = [DDMathEvaluator sharedMathEvaluator];
[evaluator registerFunction:^DDExpression *(NSArray *args, NSDictionary *vars, DDMathEvaluator *eval, NSError *__autoreleasing *error) {
NSNumber *argValue = nil;
if ([args count] == 1) {
// defaultZero() only supports a single argument
// for anything else, return 0
DDExpression *arg = [args objectAtIndex:0];
NSError *argError = nil;
argValue = [eval evaluateExpression:arg withSubstitutions:vars error:&argError];
}
if (argValue == nil) {
// return 0 if either the arg can't be eval'd or there isn't 1 arg
argValue = @0;
}
return [DDExpression numberExpressionWithNumber:argValue];
} forName:@"defaultZero"];
Upvotes: 2
Reputation: 318924
Initialize the substitution dictionary with appropriate default values first, then update it with any actual values.
Upvotes: 3