链式expression式在Core Data中执行计算
首先:新年快乐:-)
我正在尝试做什么
我试图在核心数据中划分两个属性,然后计算这些分区的平均值。 属性由关键path(例如eur
, usd
, aud
)指定。
示例:我有以下数据集:
date eur usd aud ------------------------------ 2010-01-01 0.5 1.0 1.5 2010-01-02 0.6 1.1 1.6 2010-01-03 0.4 1.0 1.3
将两个属性分开,例如eur / usd与下面的结果…
divide eur / usd: ------------------ 2010-01-01 0.5 2010-01-02 0.54 2010-01-03 0.4
…然后计算这些数字的平均值(0.5 + 0.54 + 0.4)/3 = 0.48
我的代码
由于我想这些计算由Core Data直接执行,所以我创build了以下expression式和获取请求:
NSExpression *fromCurrencyPathExpression = [NSExpression expressionForKeyPath:fromCurrency.lowercaseString]; NSExpression *toCurrencyPathExpression = [NSExpression expressionForKeyPath:toCurrency.lowercaseString]; NSExpression *divisionExpression = [NSExpression expressionForFunction:@"divide:by:" arguments:@[fromCurrencyPathExpression, toCurrencyPathExpression]]; NSExpression *averageExpression = [NSExpression expressionForFunction:@"average:" arguments:@[divisionExpression]]; NSString *expressionName = @"averageRate"; NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init]; expressionDescription.name = expressionName; expressionDescription.expression = averageExpression; expressionDescription.expressionResultType= NSDoubleAttributeType; NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([self class])]; NSPredicate *predicate = [NSPredicate predicateWithFormat:@"date >= %@ AND date <= %@",startDate,fiscalPeriod.endDate]; request.predicate = predicate; request.propertiesToFetch = @[expressionDescription]; request.resultType = NSDictionaryResultType; NSError *error; NSArray *results = [context executeFetchRequest:request error:&error];
问题
但是,运行应用程序时,它会崩溃,并显示错误消息:
Unsupported argument to sum : ( "eur / usd"
我的代码有什么问题? 我如何链接两个计算,并让他们直接在Core Data中执行?
谢谢!
似乎像@average
这样的“集合”函数expression式只能用于关键path,而不能与其他通用expression式结合使用,当用作propertiesToFetch
。 我没有这方面的参考,但也是别人也注意到的一个问题:
- 使用另一个expression式作为sum:expression的参数从NSManagedObject获取聚合数据
- 用CoreData执行乘法(聚合):如何?
所以你可以分两步进行:首先执行一个获取请求,返回一个包含所有分区结果的数组:
NSExpression *fromCurrencyPathExpression = [NSExpression expressionForKeyPath:@"eur"]; NSExpression *toCurrencyPathExpression = [NSExpression expressionForKeyPath:@"usd"]; NSExpression *divisionExpression = [NSExpression expressionForFunction:@"divide:by:" arguments:@[fromCurrencyPathExpression, toCurrencyPathExpression]]; NSString *expressionName = @"ratio"; NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init]; expressionDescription.name = expressionName; expressionDescription.expression = divisionExpression; expressionDescription.expressionResultType= NSDoubleAttributeType; NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Entity"]; request.propertiesToFetch = @[expressionDescription]; request.resultType = NSDictionaryResultType; NSError *error; NSArray *ratios = [context executeFetchRequest:request error:&error];
结果是一个字典数组:
(lldb) po ratios (NSArray *) $0 = 0x00000001001170f0 <_PFArray 0x1001170f0>( { ratio = "0.5454545454545454"; }, { ratio = "0.4"; }, { ratio = "0.5"; } )
另外,使用“-com.apple.CoreData.SQLDebug 1”选项,可以看到分区已经在SQLite级别上执行了:
sql: SELECT t0.ZEUR / t0.ZUSD FROM ZENTITY t0
然后,您可以使用键值编码来计算内存中所有比例的平均值:
NSNumber *average = [ratios valueForKeyPath:@"@avg.ratio"];
结果是
(lldb) po average (NSNumber *) $0 = 0x000000010012fd60 0.4818181818181818