Core Data Sum of All Instances Attribute

Core Data sum of all instances attribute

Having a managedObjectContext:

NSManagedObjectContext *managedObjectContext = ...

We create a fetch request with return type dictionary:

NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([Movement class])];
fetchRequest.resultType = NSDictionaryResultType;

Then we create an expression description to calculate the sum:

NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];
expressionDescription.name = @"sumOfAmounts";
expressionDescription.expression = [NSExpression expressionForKeyPath:@"@sum.amount"];
expressionDescription.expressionResultType = NSDecimalAttributeType;

Set the request properties to fetch:

fetchRequest.propertiesToFetch = @[expressionDescription];

We could also set a predicate if we want.

And last we execute the request and get an array containing a dictionary with one key(@"sumOfAmounts") and its value is a NSNumber with the sum of amounts.

NSError *error = nil;
NSArray *result = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
if (result == nil)
{
NSLog(@"Error: %@", error);
}
else
{
NSNumber *sumOfAmounts = [[result objectAtIndex:0] objectForKey:@"sumOfAmounts"];
}

Cheers

How to sum filtered Core Data in SwiftUI?

I have found similar problem in this question:
Sum of (double) fetch request field
I have modified the code a little and came up with this solution:

import SwiftUI
import CoreData

struct DashboardView: View {
@Environment(\.managedObjectContext) var managedObjectContext
// FetchRequest with predicate set to "after now"
@FetchRequest(entity: NPTransaction.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \NPTransaction.value, ascending: false)], predicate: NSPredicate(format: "date > %@", Date() as NSDate)) var fetchRequest: FetchedResults<NPTransaction>

// sum results using reduce
var sum: Int64 {
fetchRequest.reduce(0) { $0 + $1.value }
}

var body: some View {
NavigationView {
VStack(alignment: .leading) {

HStack {
VStack(alignment: .leading) {
Text("sum")
Text("\(sum)")
.font(.largeTitle)

}
Spacer()
}
.padding()

Spacer()
}.navigationBarTitle("Title")
}
}

}

struct DashboardView_Previews: PreviewProvider {
static var previews: some View {
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
return DashboardView().environment(\.managedObjectContext, context)
}
}

How to get Total Sum of all entries in a Core Data attribute?

You can use NSExpressionDescription to get the sum directly via fetch request (without fetching the managed objects themselves, which can be inefficient if you have many of them).

Remember to set NSDictionaryResultType for the fetch request (I got EXC_BAD_ACCESS if I didn't do that).

NSExpression *keyExpression = [NSExpression expressionForKeyPath:@"numberOfSeconds"];
NSExpression *sumExpression = [NSExpression expressionForFunction:@"sum:" arguments:@[keyExpression]];

NSExpressionDescription *sumDescription = [[NSExpressionDescription alloc] init];
sumDescription.name = @"sumOfSeconds";
sumDescription.expression = sumExpression;
[sumDescription setExpressionResultType:NSDecimalAttributeType];

NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Entity"];
request.resultType = NSDictionaryResultType;
[request setPropertiesToFetch:@[sumDescription]];

NSError *error = nil;
NSManagedObjectContext *context = ... //get the context somehow
NSArray* fetchResult = [context executeFetchRequest:request error:&error];
NSNumber *sum = fetchResult.firstObject[sumDescription.name]; //this is your sum

Reference: Apple Core Data guide

Sum of an attribute from all objects in a core data entity

Your raw transactions is set of transactions managedObject.Create a variable called count and run a for loop and add money.

var count = 0
for trans in member.transtion {
count = trans.money + count
}

Sum of values from Core Data entity for a different Attribute value

You could do it all in the query using group by and a dictionary result. Simpler perhaps is to just collapse the n^^2 algorithm used to compute the duration into:

let result = records.reduce(into: [:]) { acc, record in
acc[record.title, default:0.0] += record.duration
}

That will build a dictionary of title to total duration in close to order n time.

If you really want two arrays, you can add:

.reduce(into: ([String](), [Double]())) {
$0.0.append($1.key)
$0.1.append($1.value)
}

Core Data, Get Sum Of Certain Boolean Value Attribute

Since your property is a boolean, you can make it a lot simpler than the methods described in that answer. Use a predicate to match the value of passed and then get the count of the result instead of the fetched objects. Something like:

NSFetchRequest<Event *> *fetchRequest = MyEntity.fetchRequest;
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"passed = true"];
NSError *error = nil;
NSUInteger count = [self.managedObjectContext countForFetchRequest:fetchRequest error:&error];

Then count has the number of instances where passed is true.

How to Sum in Core Data

no matter what it works as this:

let fetchRequest = NSFetchRequest<NSDictionary>(entityName:"Trade")

fetchRequest.predicate = NSPredicate(format: "year = %d and month = %d",year,month)

// sort by day
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "day", ascending: true)]

//group by day for sum
fetchRequest.propertiesToGroupBy = ["day"]
var expressionDescriptions = [AnyObject]()
var expD = NSExpressionDescription()

// select day
expD.name = "day"
expD.expression = NSExpression(forKeyPath: "day")
expD.expressionResultType = .integer16AttributeType

expressionDescriptions.append(expD)

//select @sum.amount as dailysum
expD = NSExpressionDescription()
expD.name = "total"
expD.expression = NSExpression(forFunction: "sum:", arguments: [NSExpression(forKeyPath: "amount")])
expD.expressionResultType = .integer16AttributeType

expressionDescriptions.append(expD)

fetchRequest.propertiesToFetch = expressionDescriptions
fetchRequest.resultType = .dictionaryResultType

var result = [Int:String]()

do {
let fetchResult = try viewContext.fetch(fetchRequest)
for item in fetchResult {
result[item.value(forKey: "day") as! Int] = String(describing: item.value(forKey: "total") as! Int)}
} catch {
let nserror = error as NSError
fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
}

return result

SwiftUI: Group and Sum by Core Data Attribute

You should not have brackets around the i in [i] in. Brackets like that capture a value, but you don't have a variable to capture -- you're just getting a parameter for the closure.

ForEach(group(items), id: \.self) { i in

On your next line, you're dealing with a multidimensional array. You can't access a property directly, but you could map first:

Text("\(i.map(\.cost).reduce(0,+))")

You could also structure this slightly differently and remove the map by doing:

i.reduce(0,{ $0 + $1.cost })


Related Topics



Leave a reply



Submit