DDMathParser:如何定义变量的默认值

时间:2013-01-18 15:36:29

标签: ios objective-c parsing nsdictionary nspredicate

我使用DDMathParser来解析公式并计算结果,效果很好。

问题:

如果替换字典中不存在变量,是否可以将变量设置为默认值?

示例:

我的公式$a + $b需要两个变量$a$b。但是,我的替换字典仅包含变量键a的值(例如1),但不包含键b

将变量b定义为0作为默认值并避免解析错误消息"unable to resolve variable"的首选方法是什么?

谢谢!

修改

我使用DDMathParser的方式是循环遍历多个公式并为每个公式提供相同的变量替换字典。有时,我没有变量的值:在这种情况下,变量(键和值)不会包含在字典中。

根据公式本身,如果其中一个变量不存在,我希望返回nil作为公式的结果(例如,我没有profit的值和公式是$profit / $revenue,我想返回nil,我可以将NSString转换为n/a之后的0或将变量设置为$profitA + $profitB + $profitC字典中不存在(例如,对于像0这样的公式,我想假设$profitA表示任何缺失的变量($profitB$profitC0) 。

出于这个原因,我不能使用通用解决方案,它总是返回nil或{{1}},但需要将此逻辑放在公式中(例如作为自定义函数)。

2 个答案:

答案 0 :(得分:3)

首先使用适当的默认值初始化替换字典,然后使用任何实际值更新它。

答案 1 :(得分:2)

DDMathParser作者在这里。

  

如果替换字典中不存在变量,是否可以将变量设置为默认值?

有点儿。您可以通过向数学评估程序提供variableResolver块来执行此操作:

DDMathEvaluator *evaluator = [DDMathEvaluator sharedMathEvaluator];
[evaluator setVariableResolver:^(NSString *variable) { return @0; }];
NSNumber *n = [evaluator evaluateString:myString withSubstitutions:mySubstitutions];

只要求值程序遇到在替换字典中找不到的变量,就会执行变量解析程序块。

  

将自定义函数添加到DDMathParser是否可行,例如defaultZero($ b),如果存在,则检索变量b,否则返回0?

嗯,聪明的主意。你可以,但你本质上是通过模仿variableResolver块的行为。您将创建一个新的DDMathFunction块并使用-[DDMathEvaluator registerFunction:forName:]告诉评估者它。

但是,我建议只提供一个可变的解析器块。它会简单得多。


以下是如何定义defaultZero函数,该函数返回参数的值或0(如果无法计算参数):

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"];