2

I have an NSArray of names, I want to sort them alphabetically into a UITableView and separate them into sections.

I have a tagged section at the top, being section 0. I want the names sorted aplhabetically to come after that. So all names beginning with A get put into section 1, B into section 2, and so on.

I need to be able to somehow get the number of rows for each section, and then put the objects in each section.

How do I do this?

3 Answers 3

3

Here is a method for a category on NSArray to do grouping:

@interface NSArray (Grouping)
- (NSArray*) groupUsingFunction: (id (*)(id, void*)) function context: (void*) context;
@end

@implementation NSArray (Grouping)
- (NSArray*) groupUsingFunction: (id (*)(id, void*)) function context: (void*) context
{
    NSArray* groupedArray = nil;

    NSMutableDictionary* dictionary = [NSMutableDictionary new];
    if (dictionary != nil)
    {
        for (id item in self)
        {
            id key = function(item, context);
            if (key != nil)
            {
                NSMutableArray* array = [dictionary objectForKey: key];
                if (array == nil) {
                    array = [NSMutableArray arrayWithObject: item];
                    if (array != nil) {
                        [dictionary setObject: array forKey: key];
                    }
                } else {
                    [array addObject: item];
                }
            }
        }

        groupedArray = [NSMutableArray arrayWithArray: [dictionary allValues]];
        [dictionary release];
    }

    return groupedArray;
}
@end

You can use it like this:

id GroupNameByFirstLetter(NSString* object, void* context)
{
    return [object substringToIndex: 1];
}

NSInteger SortGroupedNamesByFirstLetter(id left, id right, void* context)
{
    return [[left objectAtIndex: 0] characterAtIndex: 0] - [[right objectAtIndex: 0] characterAtIndex: 0];
}

NSMutableArray* names = [NSArray arrayWithObjects: @"Stefan", @"John", @"Alex",
    @"Sue", @"Aura", @"Mikki", @"Michael", @"Joe", @"Steve", @"Mac", @"Fred",
    @"Faye", @"Paul", nil];

// Group the names and then sort the groups and the contents of the groups.

groupedNames_ = [[names groupUsingFunction: GroupNameByFirstLetter context: nil] retain];

[groupedNames_ sortUsingFunction: SortGroupedNamesByFirstLetter context: nil];

for (NSUInteger i = 0; i < [groupedNames_ count]; i++) {
    [[groupedNames_ objectAtIndex: i] sortUsingSelector: @selector(compare:)];
}
Sign up to request clarification or add additional context in comments.

Comments

1

I modified St3fans answer to be a bit more modern and work with Blocks instead:

@interface NSArray (Grouping)
- (NSArray*) groupUsingBlock:(NSString* (^)(id object)) block;
@end


- (NSArray*) groupUsingBlock:(NSString* (^)(id object)) block
{
    NSArray* groupedArray = nil;

    NSMutableDictionary* dictionary = [NSMutableDictionary new];
    if (dictionary != nil)
    {
        for (id item in self)
        {
            id key = block(item);
            if (key != nil)
            {
                NSMutableArray* array = [dictionary objectForKey: key];
                if (array == nil) {
                    array = [NSMutableArray arrayWithObject: item];
                    if (array != nil) {
                        [dictionary setObject: array forKey: key];
                    }
                } else {
                    [array addObject: item];
                }
            }
        }

        groupedArray = [NSMutableArray arrayWithArray: [dictionary allValues]];
        [dictionary release];
    }

    return groupedArray;
}

You can use it like this:

NSArray *grouped = [arrayToGroup groupUsingBlock:^NSString *(id object) {
        return [object valueForKey:@"name"];
}];

Comments

0

You should probably create an array of arrays, one for each letter, and store your names that way. While you can use a single array for storage, there's no quick way to do the segmentation you're looking for. Sorting, sure, but not section-ization.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.