Как решить условное уравнение в iOS

Я хочу решить условное уравнение в iOS:

Уравнение, которое я получаю из базы данных, находится в формате NSString, например:

if((height > 0), (weight+ 2 ), ( weight-1 ) )

В соответствии с нашим пониманием, если я проанализирую вышеприведенную строку и отдельное условие height>0, она будет в формате NSString. Но оценить его, как преобразовать строку в условный оператор?

После получения условного оператора уравнение может быть решено путем преобразования его в тройное уравнение следующим образом:

Bool status;

NSString *[email protected]" 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;`

Также уравнения могут динамически меняться, поэтому они не могут быть жестко закодированы. Короче, как мне решить это уравнение, которое я получаю как NSString.

Благодарим за терпение!

Ответ 1

Автор DDMathParser здесь...

Чтобы расширить на ответ Джонатана, вот как вы могли бы сделать это полностью в DDMathParser. Однако, чтобы разобрать строку как есть, вам нужно сделать две вещи.

Сначала вам нужно создать функцию if:

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

Это создает функцию if(), которая принимает три параметра. В зависимости от того, как оценивается первый параметр, он либо оценивает результат второго, либо третьего параметра.

Другая вещь, которую вам нужно будет сделать, - сказать оценщику, что означают height и weight. Поскольку они не начинаются с символа $, они интерпретируются как функции, а не переменные. Если они начинаются с $, то это будет так же просто, как оценить это следующим образом:

NSString *expression = @"if(($height > 0), ($weight+ 2 ), ( $weight-1 ) )";
NSDictionary *variables = @{@"height" : @42, @"weight" : @13};
NSNumber *result = [expression evaluateWithSubstitutions:variables evaluator:evaluator error:nil];

Однако, поскольку они не начинаются с $, они являются функциями, а это означает, что вам нужно сообщить оценщику, что оценивают функции. Вы можете сделать это, создав функции для height и weight, как и для if:

[evaluator registerFunction:^DDExpression *(NSArray *args, NSDictionary *vars, DDMathEvaluator *eval, NSError **error) {
    return [DDExpression numberExpressionWithNumber:@42];
} forName:@"height"];

В качестве альтернативы вы можете сделать его более динамичным и использовать блок functionResolver DDMathEvaluator, который является блоком, который возвращает блок (woooooo), и будет выглядеть так:

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

С этими двумя частями на месте (регистрируя if и предоставляя значения height и weight), вы можете сделать:

NSString *expression = @"if((height > 0), (weight+ 2 ), ( weight-1 ) )";
NSNumber *result = [expression evaluateWithSubstitutions:nil evaluator:evaluator error:nil];

... и верните правильный результат @15.

(У меня есть планы сделать DDMathParser разрешить неизвестным функциям вернуться к предоставленным значениям переменных, но я еще не закончил его)

Ответ 2

вам придется написать собственный интерпретатор или найти тот, который поддерживает такие выражения.

Первая часть (условие) может быть оценена с помощью NSPredicate. Для второй части (вычисления) вам понадобится оценка математического выражения. Попробуйте это https://github.com/davedelong/DDMathParser. Возможно, вы можете сделать оба с DDMathParser, но я не уверен.