How do I create an Objective-C NSDictionary of NSArrays without reusing the same NSArray?

15,430

I think you want to do something like this:

NSMutableDictionary *places = [[NSMutableDictionary alloc] init];

// initialize places with an array for each letter
NSString *alphabet = [[NSString alloc] initWithString:@"ABCDEFGHIJKLMNOPQRSTUVWXYZ"];
for (int x = 0; x < 26; x++) {
    NSString *letter = [alphabet substringWithRange:NSMakeRange(x, 1)];
    [places setObject:[NSMutableArray array] forKey:letter];
}

// then put each place in the array corresponding to its first letter
for (NSString *place in allPlaces) {
    NSString *first = [[place substringWithRange:NSMakeRange(0, 1)] uppercaseString];
    NSMutableArray *letterArray = [places objectForKey:first];
    [letterArray addObject:place];
}
Share:
15,430
billmaya
Author by

billmaya

Updated on June 05, 2022

Comments

  • billmaya
    billmaya almost 2 years

    Long time Windows developer, 1st time Objective-C/iPhone developer wants to create a NSDictionary of NSArrays that can be displayed in a plain UITableView with alphabetic sections.

    The source for this dictionary of arrays is an array containing store names sorted alphabetically:

    Apple Store
    Atlanta Bread Company
    Borders
    Build-A-Bear Workshop
    Cargill Gallery
    Dillards
    Dick's Sporting Goods
    Eddie Baure
    FootLocker
    GameStop
    Heizberg Diamonds
    LensCrafters
    McDonald's
    Nordstrom
    Payless Shoe Source
    Pottery Barn
    Solstice
    Starbucks Coffee
    Victoria's Secret
    White Barn Candle Co.

    The dictionary of arrays that's created from the source should look something like this (datatype in parenthesis):

    Root (Dictionary)
    ....A (Array)
    ........Apple Store (String)
    ........Atlanta Bread Company (String)
    ....B (Array)
    ........Borders (String)
    ........Build-A-Bear Workshop (String)
    ....C (Array)
    ........Cargill Gallery (String)
    ....D (Array)
    ........Dillards (String)
    ........Dick's Sporting Goods (String)
    ....etc.

    A dictionary of arrays like the above structure populates the TableView and displays like this:

    A
    Apple Store
    Atlanta Bread Company
    B
    Borders
    Build-A-Bear Workshop
    C
    Cargill Gallery
    D
    Dillards
    Dick's Sporting Goods
    etc.

    The code I've written that creates the dictionary of arrays ends up putting the last store (White Barn Candle Co.) after every section header.

    A
    White Barn Candle Co.
    B
    White Barn Candle Co.
    C
    White Barn Candle Co.
    D
    White Barn Candle Co.
    etc.

    I realize this is happening because I reuse a temporary array, populating it with the A's, clearing it out, populating it with the B's, clearing it out, etc. Here's the actual code that creates the dictionary of arrays from the source array.

    NSMutableDictionary *places = [[NSMutableDictionary alloc] init];
    NSMutableArray *alphaPlace = [[NSMutableArray alloc] init]; 
    
    for (int x = 1; x <= 26; x++) {
        NSString *alphabet = [[NSString alloc] initWithString:@"ABCDEFGHIJKLMNOPQRSTUVWXYZ"];
        NSString *letter = [alphabet substringWithRange:NSMakeRange(x - 1, 1)];
    
        for (NSString *place in allPlaces) {
            NSString *first = [place substringWithRange:NSMakeRange(0, 1)];
            if ([first isEqualToString:letter] == YES) { // Add to alphaPlace
                [alphaPlace addObject:place];
            }
            else { // Add alphaPlace to places, clear out alphaPlace; add new item to alphaPlace
                [places setValue:alphaPlace forKey:letter];
                [alphaPlace removeAllObjects];  // SAME ARRAY BEING USED FOR ALL LETTERS OF ALPHABET!
                [alphaPlace addObject:place];
            }
        }
    }
    

    I realize I could "brute force" this by creating 26 distinct arrays and using a switch statement to select the correct one to populate but I really don't want to do that. I thought someone more familiar with Objective-C could provide me with a more elegant solution.

    Thanks in advance. Let me know if you need more info.