iOS根据现有数组中的对象创建一个新数组?

时间:2014-08-12 12:35:01

标签: ios objective-c nsarray

我有Expense个对象的数组(比如expenseArray)。费用有像catId,amount,name等属性。现在我想在SQL中执行group by和其他一些条款。即在新数组中,我的对象应该基于catId进行分组,并且应该将它们的数量相加。 例如,如果我在expensesArray中有2个元素,每个元素包含catId=2amount=20,那么新数组应该只包含一个catId=2amount=40的元素。 这是我尝试过的代码:

[groupedExpesesArray addObject:[self createExpenseModel:[expensesArray objectAtIndex:0]]];

ExpenseModel* expenseMObj = [groupedExpesesArray objectAtIndex:0];

for (int j = 1; j < expensesArray.count; j++) 
{            
    ExpenseModel* expModel = [self createExpenseModel:[expensesArray objectAtIndex:j]];

    if ([expModel.categoryID isEqual:expenseMObj.categoryID])
    {
      float amt = [expenseMObj.amount floatValue];
      amt = amt+[expModel.amount doubleValue];
      expenseMObj.amount = [NSNumber numberWithFloat:amt];
    }
    else
    {
      int index = [groupedExpesesArray indexOfObject:expModel];
      if (index == NSNotFound)
      {
         [groupedExpesesArray addObject:expModel];
      }
    }
 }

但我仍然无法获得所需的价值。所以我需要一些关于我在这里出错的地方以及可能的解决步骤的指导。

修改: - 我正在Expense方法中创建createExpenseModel:的新对象。并检查它是否在groupedExpesesArray中可用。也许这就是问题所在。不是吗? 任何建议将不胜感激。 感谢。

3 个答案:

答案 0 :(得分:0)

基于this answer

NSArray *array = @[@{@"groupId" : @"1", @"price" : @20},
                   @{@"groupId" : @"2", @"price" : @1},
                   @{@"groupId" : @"3", @"price" : @2},
                   @{@"groupId" : @"4", @"price" : @3},
                   @{@"groupId" : @"1", @"price" : @30},
                   @{@"groupId" : @"2", @"price" : @5},
                   @{@"groupId" : @"3", @"price" : @100},
                   @{@"groupId" : @"4", @"price" : @7},
                   @{@"groupId" : @"1", @"price" : @200},
                   @{@"groupId" : @"2", @"price" : @9},
                   @{@"groupId" : @"3", @"price" : @10},
                   ];

NSMutableArray *resultArray = [NSMutableArray new];
NSArray *groups = [array valueForKeyPath:@"@distinctUnionOfObjects.groupId"];
for (NSString *groupId in groups)
{
    NSMutableDictionary *entry = [NSMutableDictionary new];
    [entry setObject:groupId forKey:@"groupId"];

    NSArray *groupedEntires = [array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"groupId = %@", groupId]];
    CGFloat sum = 0;
    for (NSDictionary *dict in groupedEntires)
    {
        NSNumber *price = [dict objectForKey:@"price"];
        sum += [price floatValue];

    }
    [entry setObject:@(sum) forKey:@"price"];
    sum = 0;
    [resultArray addObject:entry];
}

结果:

{
    groupId = 3;
    price = 112;
},
{
    groupId = 4;
    price = 10;
},
{
    groupId = 1;
    price = 250;
},
{
    groupId = 2;
    price = 15;
}
)

答案 1 :(得分:0)

我不知道我是否理解得很好,但可以通过类似的方式来完成

//This will filter the array grouping object by the same ID
NSPredicate * predicate = [NSPredicate predicateWithFormat:@"catID == %d",index];
NSArray * arrayGroup = [expensesArray filteredArrayUsingPredicate:predicate];
//Sum their amount
NSNumber * totalAmount = [arrayGroup valueForKeyPath:@"@sum.amount"];

您可以将其放入循环中,并通过获取每个单个过滤组数组的第一个对象来重新创建值。可能它不是最快的方式,但应该有效。

答案 2 :(得分:0)

假设你有一个这样的模型对象类:

<强> Expense.h

NS_ENUM(NSUInteger, ExpenseType) {
    ExpenseTypeMeals,
    ExpenseTypeLodging,
    ExpenseTypeTravel
};

@interface Expense : NSObject

@property (assign, nonatomic) NSUInteger categoryID;
@property (assign, nonatomic) float amount;

- (instancetype)initWithCategoryID:(NSUInteger)categoryID amount:(float)amount;
+ (instancetype)expenseWithCategoryID:(NSUInteger)categoryID amount:(float)amount;
@end

<强> Expense.m

@implementation Expense

- (instancetype)initWithCategoryID:(NSUInteger)categoryID amount:(float)amount
{
    if (!(self = [super init])) return nil;
    _categoryID = categoryID;
    _amount = amount;
    return self;
}

+ (instancetype)expenseWithCategoryID:(NSUInteger)categoryID amount:(float)amount
{
    return [[Expense alloc] initWithCategoryID:categoryID amount:amount];
}

- (NSString *)description
{
    return [NSString stringWithFormat:@"categoryID: %@, amount: %.2f", @(self.categoryID), self.amount];
}
@end

...并给出了一系列Expense对象:

NSArray *expenses = @[[Expense expenseWithCategoryID:ExpenseTypeMeals amount:32.50],
                      [Expense expenseWithCategoryID:ExpenseTypeMeals amount:12.95],
                      [Expense expenseWithCategoryID:ExpenseTypeLodging amount:125.45],
                      [Expense expenseWithCategoryID:ExpenseTypeLodging amount:125.45]];

...然后你可以做类似以下的事情:

// Use Key-Value Coding (KVC) collection operator to obtain an array of category IDs.
NSArray *categoryIDs = [expenses valueForKeyPath:@"@distinctUnionOfObjects.categoryID"];
NSMutableArray *totalsByCategory = [NSMutableArray arrayWithCapacity:categoryIDs.count];

for (NSNumber *categoryID in categoryIDs)
{
    // Use a predicate to a filtered array of Expense objects that match the current category ID.
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"categoryID = %@", categoryID];
    NSArray *expensesForCategory = [expenses filteredArrayUsingPredicate:predicate];

    // Use a KVC collection operator to sum of the amount properties of the Expense objects.
    NSNumber *sum = [expensesForCategory valueForKeyPath:@"@sum.amount"];

    [totalsByCategory addObject:[Expense expenseWithCategoryID:categoryID.intValue amount:sum.floatValue]];
}

NSLog(@"%@", totalsByCategory);

...与结果输出......

2014-08-12 11:08:32.692 MyExpenses[9691:303] (
    "categoryID: 0, amount: 45.45",
    "categoryID: 1, amount: 250.90"
)