1

複雑なコア データ フェッチ リクエストを作成する必要がありますが、作成できるかどうかわかりません。これは私のシナリオです: これらの属性を持つ 1 つのエンティティ (経費) のみ:

  • コスト(NSDecimalNumber)
  • 預金(NSDecimalNumber)
  • カテゴリ(NSString)
  • 有料(ブール値)

要求は 3 つの最も高価なカテゴリを返す必要がありますが、これらは尊重する必要があるルールです。

  • Paid == YESの場合、費用は費用カテゴリの合計に追加する必要があります
  • Paid == NO && Deposit > 0の場合、費用のデポジットを費用カテゴリの合計に追加する必要があります
  • Paid == NOの場合、経費カテゴリの合計には何も追加されません

NSExpression を使用すると、カテゴリごとにすべての合計を計算できますが、未払いの費用も含まれます。これを達成する方法はありますか?どうもありがとう!

4

1 に答える 1

1

たとえば、次のように使用できますNSFetchRequest

// Build the fetch request
NSString *entityName = NSStringFromClass([Expense class]);
NSFetchRequest *request = [[NSFetchRequest alloc] init];
request.entity = entity;

関連する費用のみをフィルタリングします。

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(paid == YES) OR ((paid == NO) AND (deposit > 0))"];
request.predicate = predicate;

cost 属性と depost 属性を合計します。

NSExpressionDescription *(^makeExpressionDescription)(NSString *, NSString *) = ^(NSString *keyPath, NSString *name)
{
    // Create an expression for the key path.
    NSExpression *keyPathExpression = [NSExpression expressionForKeyPath:keyPath];

    // Create an expression to represent the function you want to apply
    NSExpression *totalExpression = [NSExpression expressionForFunction: @"sum:" arguments: @[keyPathExpression]];

    NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];

    // The name is the key that will be used in the dictionary for the return value
    expressionDescription.name = name;
    expressionDescription.expression = totalExpression;
    expressionDescription.expressionResultType = NSDecimalAttributeType;

    return expressionDescription;
};

NSExpressionDescription *totalCostDescription = makeExpressionDescription(@"cost", @"totalCost");
NSExpressionDescription *totalDepositDescription = makeExpressionDescription(@"deposit", @"totalDeposit");

// Specify that the request should return dictionaries.
request.resultType = NSDictionaryResultType;

request.propertiesToFetch = @[categoryDescription,
                              paidDescription,
                              totalCostDescription,
                              totalDepositDescription];

結果をカテゴリと有料ステータスでグループ化します。

// Get 'category' and 'paid' attribute descriptions
NSEntityDescription *entity = [NSEntityDescription entityForName:entityName
                                              inManagedObjectContext:context];
NSDictionary *attributes = [entity attributesByName];
NSAttributeDescription *categoryDescription = attributes[@"category"];
NSAttributeDescription *paidDescription = attributes[@"paid"];

// Group by 'category' and 'paid' attributes
request.propertiesToGroupBy = @[categoryDescription, paidDescription];

有償と未払の費用が合算されます

NSError *error = nil;
NSArray *results = [context executeFetchRequest:request error:&error];

あなたがする必要があるのは、結合(およびソート)することだけです:

if (results) {
    NSMutableDictionary *combined = [NSMutableDictionary dictionary];

    for (NSDictionary *result in results) {
        NSString *category = result[@"category"];

        BOOL paid = [result[@"paid"] boolValue];

        NSDecimalNumber *total = result[paid ? @"totalCost" : @"totalDeposit"];

        NSDecimalNumber *sum = combined[category];

        if (sum) {
            total = [total decimalNumberByAdding:sum];
        }

        combined[category] = total;
    }

    NSArray *sortedCategories = [combined keysSortedByValueUsingSelector:@selector(compare:)];

    [sortedCategories enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        NSLog(@"Category %@: %@", obj, combined[obj]);
    }];
}
else {
    NSLog(@"Error: %@", error);
}
于 2013-08-31T21:51:16.037 に答える