2013-01-15 38 views
4

我們有一個應用程序,它調用SOAP Web服務並檢索一長串XML,然後應用程序將其解析爲NSDictionary對象的NSArrayNSArray包含租賃公寓信息的列表,其中每個信息都存儲在NSDictionary中。根據NSDictionary鍵值將NSArray拆分成子數組

整個列表可能包含10種不同類型的公寓(即兩房三房),我們需要根據房型分成NSArray小房型,其中房型爲「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]; 
} 

但是,由於原始列表可能包含大量(> 100,000)的項目,因此步驟3需要很長時間。似乎NSPredicate遍歷每個鍵值的整個列表。根據NSDictionary密鑰,是否有更高效的方式將較大的NSArray拆分爲更小的NSArray

回答

3

如果您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]; 
+0

感謝Jonathan的快速回復!將嘗試它,並測試性能是否更好使用此。似乎至少我們必須循環整個原始數組一次...... – AndyV

1

這是非常高性能

- (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; 
} 
0

提高@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]; 
    } 
    

希望,這將有助於客戶端時,最終要數組與輸入數組的順序相同。