Да, вы можете сделать это. Это относится к категории «Использование NSPredicate
для вещей, для которых оно не было предназначено», но будет работать просто отлично.
Вам необходимо заменить переменные одним словом, которое начинается с $
, поскольку NSPredicate
обозначает переменные:
NSPredicate *p = [NSPredicate predicateWithFormat:@"foo = $bar"];
Как бы ты не хотел это делать, отлично. NSRegularExpression
это прекрасный способ сделать это.
Как только вы это сделаете, у вас будет что-то вроде этого:
@"$profitability2011 = $profit2011 / $revenue2011"
Затем вы можете вставить это через +predicateWithFormat:
. Вы получите обратно NSComparisonPredicate
. -leftExpression
будет иметь тип NSVariableExpressionType
, а -rightExpression
будет иметь тип NSFunctionExpressionType
.
Вот тут-то и начинают волосатые вещи. Если бы вы были -evaluteWithObject:substitutionVariables:
, вы бы просто вернули значение YES
или NO
, поскольку предикат - это просто утверждение, которое оценивается как true или false . Я не исследовал, как вы могли бы просто оценить одну сторону (в данном случае -rightExpression
), но возможно, что -[NSExpression expressionValueWithObject:context:]
может вам помочь. Я не знаю, потому что я не уверен, для чего этот параметр "context". Это не кажется как словарь подстановки, но я могу ошибаться.
Так что, если это не сработает (и я понятия не имею, будет ли это или нет), вы можете использовать мой парсер: DDMathParser . У него есть синтаксический анализатор, похожий на синтаксический анализатор NSPredicate
, но он специально настроен для анализа и вычисления математических выражений. В вашем случае вы бы сделали:
#import "DDMathParser.h"
NSString *s = @"$profit2011 / $revenue2011";
NSDictionary *values = ...; // the values of the variables
NSNumber *profitability = [s numberByEvaluatingStringWithSubstitutions:values];
Документация для DDMathParser
довольно обширна , и она может сделать совсем немного.
edit Разрешение динамической переменной
Я только что выдвинул изменение, которое позволяет DDMathParser динамически разрешать функции. Важно понимать, что функция отличается от переменной. Функция оценивается, а переменная просто подставляется. Однако изменение влияет только на динамическое разрешение для функций , а не переменных. Это нормально, потому что в DDMathParser есть такая замечательная вещь, которая называется без аргументов .
Функция без аргументов - это имя функции, за которым не следует открывающая скобка. Для удобства он вставлен для вас. Это означает, что @"pi"
правильно проанализирован как @"pi()"
(поскольку константа для & pi; реализована как функция).
В вашем случае вы можете сделать это:
Вместо регулярного выражения вашей строки для создания переменных просто используйте имена терминов:
@"profit_2011 / revenue_2011";
Это будет проанализировано, как если бы вы ввели:
@"divide(profit_2011(), revenue_2011())"
Вы можете настроить объект DDMathEvaluator
с помощью функции распознавателя. В хранилище DDMathParser
есть два примера:
- В этом примере показано, как использовать функцию распознавателя для поиска «отсутствующей» функции в словаре подстановки (это будет наиболее похоже на то, что вы хотите)
- В этом примере показано, как интерпретировать любую отсутствующую функцию, как если бы она была оценена как 42.
Как только вы реализуете функцию распознавателя, вы можете отказаться от упаковки всех ваших переменных в словарь.