使用NSExpression expressionForSubquery有条件地对数据求和

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用NSExpression expressionForSubquery有条件地对数据求和相关的知识,希望对你有一定的参考价值。

我有下表,我想获取fileSize字段数据的总和,isSelectedForSync标志将为YES。

这是DigitalLibrary表属性

TableName:DigitalLibrary

属性及其类型:

  • digitalLibraryID(NSNumber)
  • fileName(NSString)
  • connectType(NSString)
  • fileSize(NSNumber - doubleValue)
  • isSelectedForSync(NSNumber - BOOL)
  • isSync(NSNumber - BOOL)

我想获取isSelectedForSync标志为YES的文件计数。还需要获取isSelectedForSync的fileSize的总和

我在NSExpression下面尝试,但没有得到我想要的东西。它也给我错误。

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];

    NSEntityDescription* entityDescription = [NSEntityDescription entityForName:@"DigitalLibrary" inManagedObjectContext:self.managedObjectContext];

    NSDictionary *entityDict = [entityDescription propertiesByName];

    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"isSync == %@ && isSelectedForSync == %@",[NSNumber numberWithBool:NO], [NSNumber numberWithBool:YES]];

    [fetchRequest setPredicate:predicate];
    [fetchRequest setEntity:entityDescription];
    [fetchRequest setResultType:NSDictionaryResultType];
    [fetchRequest setPropertiesToGroupBy:[NSArray arrayWithObjects:[entityDict objectForKey:@"connectType"], nil]];

    //AllPhotoCount
    NSExpression *countExpression = [NSExpression expressionForFunction:@"count:"
                                                              arguments:@[[NSExpression expressionForKeyPath:@"connectType"]]];
    NSExpressionDescription *fileCountExpressionDescription = [[NSExpressionDescription alloc] init];
    [fileCountExpressionDescription setName:@"filesCount"]; // Choose an appropriate name here!
    [fileCountExpressionDescription setExpression:countExpression];
    [fileCountExpressionDescription setExpressionResultType:NSInteger32AttributeType];
//    //Selected Photo Count
    NSExpression *selectedFileExpression = [NSExpression expressionForFunction:@"sum:"
                                                                      arguments:@[[NSExpression expressionForKeyPath:@"isSelectedForSync"]]];
    NSExpressionDescription *selectedFilesExpressionDescription = [[NSExpressionDescription alloc] init];
    [selectedFilesExpressionDescription setName:@"selectionCount"]; // Choose an appropriate name here!
    [selectedFilesExpressionDescription setExpression:selectedFileExpression];
    [selectedFilesExpressionDescription setExpressionResultType:NSInteger32AttributeType];

NSString *shadowVar = @"";
    //Sum Of FileSize which file selected
//    NSExpression *keyPathSelectedFileSizeTotalExpression = [NSExpression expressionForKeyPath:@"fileSize"];
    NSExpression *selectedFileSizeTotalExpression = [NSExpression expressionForFunction:@"sum:"
                                                                              arguments:@[[NSExpression expressionForKeyPath:@"fileSize"]]];

    NSExpression *totalselectedFileSizeExpression = [NSExpression expressionForSubquery:selectedFileSizeTotalExpression usingIteratorVariable:shadowVar predicate:[NSPredicate predicateWithFormat:@"isSelectedForSync == %@",[NSNumber numberWithBool:YES]]];

    NSExpressionDescription *selectedFileSizeTotalExpressionDescription = [[NSExpressionDescription alloc] init];
    [selectedFileSizeTotalExpressionDescription setName:@"selectedFileSizeTotal"];
    [selectedFileSizeTotalExpressionDescription setExpression:totalselectedFileSizeExpression];
    [selectedFileSizeTotalExpressionDescription setExpressionResultType:NSInteger64AttributeType];

 [fetchRequest setPropertiesToFetch:@[[entityDict objectForKey:@"connectType"], fileCountExpressionDescription, selectedFileSizeTotalExpressionDescription]];

    NSLog(@"2nd shadowVar:%@",shadowVar);

    NSError* error = nil;
    NSArray *results = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];

如果我删除'selectedFileSizeTotalExpressionDescription',上面的代码工作得很好,但如上所述需要selectedFileSizeTotalExpressionDescription。

我在如何使用NSExpression expressionForSubquery方法时非常困惑。

以下是包含在DigitalLibrary表中的数据:

+-----------+--------------------+--------------+------------+
|fileSize   |isSelectedForSync   |connectType   |fileName    |
+-----------+--------------------+--------------+------------+
|1000       |0                   |Image         |temp1.png   |
+-----------+--------------------+--------------+------------+
|200        |1                   |Image         |tmp.png     |
+-----------+--------------------+--------------+------------+
|400        |1                   |Image         |tmp23.png   |
+-----------+--------------------+--------------+------------+
|20000      |1                   |Video         |test.mp4    |
+-----------+--------------------+--------------+------------+
|3000       |1                   |Audio         |temp2.mp3   |
+-----------+--------------------+--------------+------------+
|15000      |0                   |Video         |test12.mp4  |
+-----------+--------------------+--------------+------------+
|3500       |0                   |Audio         |temp12.mp3  |
+-----------+--------------------+--------------+------------+

我想得到以下结果:

+----------------+-------------------+--------------+----------------+------------------+
|TotalFileSize   |selectedFileSize   |connectType   |totalFileCount  |selectedFileCount |
+----------------+-------------------+--------------+----------------+------------------+
|1400            |600                |Image         |3               |2                 |
+----------------+-------------------+--------------+----------------+------------------+
|35000           |20000              |Video         |2               |1                 |
+----------------+-------------------+--------------+----------------+------------------+
|6500            |3000               |Audio         |2               |1                 |
+----------------+-------------------+--------------+----------------+------------------+
答案
  NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([DigitalLibrary class])];//
    NSPredicate * imageTypePredicate = [NSPredicate predicateWithFormat:@"connectType ==[c] Image"];

    [fetchRequest setPredicate:imageTypePredicate];

    NSArray * imageTypeFilteredArray = [context executeFetchRequest:fetchRequest error:nil];

    NSArray * imageFileSizeArray = [imageTypeFilteredArray valueForKey:@"fileSize"];

    double totalValue = 0.0;

    for (NSNumber * eachFileSize in imageFileSizeArray)
    {
        totalValue += [eachFileSize doubleValue];
    }

    NSPredicate * predicate = [NSPredicate predicateWithFormat:@"isSelectedForSync == YES"];
    NSArray * selectedImageFileSizeArray = [imageTypeFilteredArray filteredArrayUsingPredicate:predicate];


    double totalSelectedValue = 0.0;

    for (NSNumber * eachFileSize in selectedImageFileSizeArray)
    {
        totalSelectedValue += [eachFileSize doubleValue];
    }

同样可以用于视频和音频。

以上是关于使用NSExpression expressionForSubquery有条件地对数据求和的主要内容,如果未能解决你的问题,请参考以下文章

使用 NSExpression 计算小于值?

使用“现在”的 NSExpression 函数

使用 NSExpression 时捕获 NSInvalidArgumentException 的正确方法 [重复]

NSExpression 捕获无效参数

NSExpression 使用 sqrt: 函数导致 NSInvalidArgumentException

如何使用 NSExpression 使用自定义函数设置 NSFetchRequest propertiesToFetch