4

SOAP Web サービスを呼び出して XML の長いリストを取得するアプリがあり、アプリはそれを解析してオブジェクトNSArrayの. NSDictionaryには賃貸マンション情報のNSArrayリストが含まれており、それぞれが に格納されていNSDictionaryます。

リスト全体には、10 の異なるタイプのアパートメント (つまり、2 部屋、3 部屋) が含まれている可能性があり、オブジェクトにキー「roomType」を持つ Room-Type に基づいて、NSArray小さなに分割する必要があります。NSArrayNSDictionary

現在、私たちのアルゴリズムは

  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各キー値のリスト全体を通過するようです。キーに基づいて、大きなものNSArrayを小さなものに分割するより効率的な方法はありますか?NSArrayNSDictionary

4

3 に答える 3

3

分割された配列の順序が重要でない場合は、解決策があります。

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];
于 2013-01-15T10:25:12.687 に答える
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;
}
于 2014-03-14T13:32:47.950 に答える
0

@ジョナサンの回答の改善

  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];
    }
    

クライアントが入力配列と同じ順序で最終配列を必要とする場合に役立つことを願っています。

于 2016-07-20T04:43:41.650 に答える