NSArray的分割成子阵列基于NSDictionary的键值(Split NSArray into

2019-08-06 21:55发布

我们有一个调用SOAP的Web服务和XML检索一个长长的清单,该应用程序,然后解析到一个应用程序NSArrayNSDictionary对象。 该NSArray包含的出租公寓的信息,每个被存储到一个列表NSDictionary

整个列表可以含有10种不同类型的住宅的(即2室的三室),并且我们需要将分割NSArray成更小NSArray S的基于房间型,其具有在所述键“roomType” NSDictionary对象。

目前,我们的算法是

  1. 使用[NSArray valueForKeyPath:@"@distinctUnionofObjects.room-type"]获得独一无二的房间类型值的列表。
  2. 通过独特的房间类型值的列表循环
  3. 对于每一个独特的客房类型值,使用NSPredicate来检索原始列表匹配的项目

我们的代码如下(已更名为清楚起见):

NSArray *arrOriginal = ... ...; // Contains the Parsed XML list

NSMutableArray *marrApartmentsByRoomType = [NSMutableArray arrayWithCapacity:10];

NSMutableArray *arrRoomTypes = [arrOriginal valueForKeyPath:@"distinctUnionOfObjects.roomType"];

for(NSString *strRoomType in arrRoomTypes) {
  NSPredicate *predicateRoomType = [NSPredicate predicateWithFormat:@"roomType=%@", strRoomType];

  NSArray *arrApartmentsThatMatchRoomType = [arrOriginal filteredArrayUsingPredicate:predicateRoomType];  // TAKES A LONG TIME EACH LOOP-ROUND

  [marrApartmentsByRoomType addObject:arrApartmentsThatMatchRoomType];
}

然而,步骤3,取放物品的时​​间长为原始列表可以包含大量(> 100,000)。 看来, NSPredicate经过每个键值整个列表。 有没有分裂大的更有效的方法NSArray成更小NSArray S,基于NSDictionary钥匙?

Answer 1:

如果您splited阵列的顺序并不重要,我对你的解决方案:

NSArray *arrOriginal;
NSMutableDictionary *grouped = [[NSMutableDictionary alloc] initWithCapacity:arrOriginal.count];
for (NSDictionary *dict in arrOriginal) {
    id key = [dict valueForKey:@"roomType"];

    NSMutableArray *tmp = [grouped objectForKey:key];
    if (tmp == nil) {
        tmp = [[NSMutableArray alloc] init];
        [grouped setObject:tmp forKey:key];
    }
    [tmp addObject:dict];
}
NSMutableArray *marrApartmentsByRoomType = [grouped allValues];


Answer 2:

这是相当高性能

- (NSDictionary *)groupObjectsInArray:(NSArray *)array byKey:(id <NSCopying> (^)(id item))keyForItemBlock
{
    NSMutableDictionary *groupedItems = [NSMutableDictionary new];
    for (id item in array) {
        id <NSCopying> key = keyForItemBlock(item);
        NSParameterAssert(key);

        NSMutableArray *arrayForKey = groupedItems[key];
        if (arrayForKey == nil) {
            arrayForKey = [NSMutableArray new];
            groupedItems[key] = arrayForKey;
        }
        [arrayForKey addObject:item];
    }
    return groupedItems;
}


Answer 3:

提高@Jonathan答案

  1. 转换阵列到字典
  2. 保持相同的顺序,因为它在原始阵列

     //only to a take unique keys. (key order should be maintained) NSMutableArray *aMutableArray = [[NSMutableArray alloc]init]; NSMutableDictionary *dictFromArray = [NSMutableDictionary dictionary]; for (NSDictionary *eachDict in arrOriginal) { //Collecting all unique key in order of initial array NSString *eachKey = [eachDict objectForKey:@"roomType"]; if (![aMutableArray containsObject:eachKey]) { [aMutableArray addObject:eachKey]; } NSMutableArray *tmp = [grouped objectForKey:key]; tmp = [dictFromArray objectForKey:eachKey]; if (!tmp) { tmp = [NSMutableArray array]; [dictFromArray setObject:tmp forKey:eachKey]; } [tmp addObject:eachDict]; } //NSLog(@"dictFromArray %@",dictFromArray); //NSLog(@"Unique Keys :: %@",aMutableArray); 

    // 从字典转换为数组再次 ...

     self.finalArray = [[NSMutableArray alloc]init]; for (NSString *uniqueKey in aMutableArray) { NSDictionary *aUniqueKeyDict = @{@"groupKey":uniqueKey,@"featureValues":[dictFromArray objectForKey:uniqueKey]}; [self.finalArray addObject:aUniqueKeyDict]; } 

希望,当客户希望在相同的顺序输入数组最后一个数组它将帮助。



文章来源: Split NSArray into sub-arrays based on NSDictionary key values