First of all: Happy new year :-)
I am trying to divide two attributes in Core Data and then calculate the average of these divisions.
It seems that "collection" function expressions like @average
can only be used with key paths, but not in combination with other general expressions, when used as propertiesToFetch
. I do not have a reference for that, but it is a problem that others have noticed also:
So you could proceed in two steps: First execute a fetch request that returns an array with the results of all divisions:
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];
The result is an array of dictionaries:
(lldb) po ratios
(NSArray *) $0 = 0x00000001001170f0 <_PFArray 0x1001170f0>(
{
ratio = "0.5454545454545454";
},
{
ratio = "0.4";
},
{
ratio = "0.5";
}
)
Also, with the "-com.apple.CoreData.SQLDebug 1" option one can see that the divisions are already executed on the SQLite level:
sql: SELECT t0.ZEUR / t0.ZUSD FROM ZENTITY t0
Then you can compute the average of all ratios in memory, using Key-Value Coding:
NSNumber *average = [ratios valueForKeyPath:@"@avg.ratio"];
and the result is
(lldb) po average
(NSNumber *) $0 = 0x000000010012fd60 0.4818181818181818