使用核心数据,我遇到了问题。我有一个实体“运动”,其属性为“金额”。如何计算所有实例的所有“金额”的总和?我想了解如何使用NSExpressionDescription
,但它已经足够NSSet
。
答案 0 :(得分:20)
拥有managedObjectContext:
NSManagedObjectContext *managedObjectContext = ...
我们使用返回类型字典创建一个获取请求:
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([Movement class])];
fetchRequest.resultType = NSDictionaryResultType;
然后我们创建一个表达式描述来计算总和:
NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];
expressionDescription.name = @"sumOfAmounts";
expressionDescription.expression = [NSExpression expressionForKeyPath:@"@sum.amount"];
expressionDescription.expressionResultType = NSDecimalAttributeType;
将请求属性设置为fetch:
fetchRequest.propertiesToFetch = @[expressionDescription];
如果需要,我们也可以设置一个谓词。
最后我们执行请求并获取一个包含带一个密钥的字典的数组(@“sumOfAmounts”),其值为NSNumber,其数量总和。
NSError *error = nil;
NSArray *result = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
if (result == nil)
{
NSLog(@"Error: %@", error);
}
else
{
NSNumber *sumOfAmounts = [[result objectAtIndex:0] objectForKey:@"sumOfAmounts"];
}
干杯
答案 1 :(得分:7)
这是使用NSExpression
和NSExpressionDescription
对托管对象属性求和的 Swift 示例。该示例假定托管对象名为 Movement
,并且要求的属性为 amount
。
示例:强>
func sumAmount() -> Double {
var amountTotal : Double = 0
// Step 1:
// - Create the summing expression on the amount attribute.
// - Name the expression result as 'amountTotal'.
// - Assign the expression result data type as a Double.
let expression = NSExpressionDescription()
expression.expression = NSExpression(forFunction: "sum:", arguments:[NSExpression(forKeyPath: "amount")])
expression.name = "amountTotal";
expression.expressionResultType = NSAttributeType.doubleAttributeType
// Step 2:
// - Create the fetch request for the Movement entity.
// - Indicate that the fetched properties are those that were
// described in `expression`.
// - Indicate that the result type is a dictionary.
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Movement")
fetchRequest.propertiesToFetch = [expression]
fetchRequest.resultType = NSFetchRequestResultType.dictionaryResultType
// Step 3:
// - Execute the fetch request which returns an array.
// - There will only be one result. Get the first array
// element and assign to 'resultMap'.
// - The summed amount value is in the dictionary as
// 'amountTotal'. This will be summed value.
do {
let results = try context.fetch(fetchRequest)
let resultMap = results[0] as! [String:Double]
amountTotal = resultMap["amountTotal"]!
} catch let error as NSError {
NSLog("Error when summing amounts: \(error.localizedDescription)")
}
return amountTotal
}
对步骤的补充讨论:
第1步 - 创建 NSExpressionDescription
变量。这个NSExpressionDescription
表示对参数应用了什么类型的函数。 总和功能正在应用于金额属性。
expression.expression = NSExpression(forFunction: "sum:",
arguments:[NSExpression(forKeyPath: "amount")])
请注意,参数参数是数组。您可以在数组中传递不同类型的表达式,但在我们的示例中,我们只需要amount
属性。
第2步 - 在此处建立获取请求。请注意,结果类型被指定为字典:fetchRequest.resultType = NSAttributeType.DictionaryResultType
。在第3步中,我们将使用expression.name
amountTotal
值作为访问求和值的键。
第3步 - 我们执行获取请求并返回将是一个元素数组。该元素将是一个字典,我们将其加速到[String:Double]
:let resultMap = results[0] as! [String:Double]
。字典的值是Double,因为在第1步中我们指出expression.expressionResultType
将是Double。
最后,我们通过调用与amountTotal
密钥相关联的字典值来访问总和:resultMap["amountTotal"]!
<强>参考文献:强>
答案 2 :(得分:2)
最好的方法是使用fetch for specific values并提供NSExpressionDescription with a sum:
function.
当您执行fetch时,您将获得一个包含字典的单元素数组,该字典的键与表达式描述匹配,其值是表达式的结果。在这种情况下,您将获得一个sum
键,其值将是给定表达式的属性的总和。