2013-05-16 3 views
10

Я хочу, чтобы решить условное уравнение прошивки:как решить условное уравнение прошивки

уравнение я получаю из базы данных в формате 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.

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

+0

Вы работаете с реальными данными в существующем формате, или вы можете использовать любого формат, который вы хотите? – tia

+0

относящийся к http://stackoverflow.com/questions/2550897/eval-for-objective-c-code – Daniel

+0

В любом случае 'height' и' weight' не будут переменной для сравнения. – rptwsthi

ответ

4

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

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

5

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

Чтобы расширить Jonathan's answer, вот как вы могли бы сделать это полностью в 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 позволяют неизвестные функции, чтобы возвратиться к обеспеченным значениям переменных, но я не совсем закончил его еще)

+0

Мне нравится начать ответ! :-) – Amar

+0

Как подойти, если уравнение имеет вызов функции Ex: 'if (xyz == 0, if (abc <0, 270, 90), atan (xyz/abc) * 180/_pi)'? – Amar

+0

@Amar до тех пор, пока вы определяете, что '_pi',' xyz' и 'abc' все, это будет работать нормально. 'atan' - встроенная функция. (Но если вы назвали его 'pi' вместо' _pi', вам не нужно было бы его определять. ['Pi' также является встроенной функцией] (https://github.com/davedelong/DDMathParser/ wiki/Встроенные функции). –

Смежные вопросы