HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

Splitting an NSArray into an NSDictionary of array more elegantly

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
nsarrayarrayintonsdictionarymoresplittingelegantly

Problem

I need to split one NSArray into NSDictionary. Every key in NSDictionary will contain an NSArray with the object with the same value.

i.e. I have an array with 1000 customers and I want create an NSDictionary based on their zip code.

I wrote this code into an NSArray category and it works, but I'm looking for a better name and a way (if it exists) to do the same job with the KVC.

-(NSDictionary *)groupArrayWithBlock:(id (^)(id obj))block {
    NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];

    for (id obj in self) {
        id key = block(obj);
        if (! dictionary[key]) {
            NSMutableArray *arr = [NSMutableArray array];
            dictionary[key] = arr;
        }
        [dictionary[key] addObject:obj];
    }
    return [dictionary copy];
}

Solution

As far as name of the method is concerned I have two points:

  • There is no need of the work Array here, as it is NSArray instance method.



  • The work With gives wrong impression here. (the phrase "group a with b" will generally mean to group them together).



So in my opinion groupUsingBlock or dictionaryGroupedUsingBlock, might be better.

Regarding KVC, if grouping is required to be done on a single property and that property is in complaint with the standard, you can have the function as following:

-(NSDictionary *)groupByKey:(NSString *) key {
    NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];

    for (id obj in self) {
        id keyValue = [obj valueForKey:key];
        NSMutableArray *arr = dictionary[keyValue];
        if (! arr) {
            arr = [NSMutableArray array];
            dictionary[keyValue] = arr;
        }
        [arr addObject:obj];
    }
    return [dictionary copy];
}


This will make the method slightly easy to use, but will also seriously limit the flexibility. So I would suggest that you keep the method which uses Block and implement the KVC version of the method by using it, like following:

-(NSDictionary *)groupByKey:(NSString *) key {
    return [self groupUsingBlock:^(id obj) {
            return [obj valueForKey:key];
        }];
}

Code Snippets

-(NSDictionary *)groupByKey:(NSString *) key {
    NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];

    for (id obj in self) {
        id keyValue = [obj valueForKey:key];
        NSMutableArray *arr = dictionary[keyValue];
        if (! arr) {
            arr = [NSMutableArray array];
            dictionary[keyValue] = arr;
        }
        [arr addObject:obj];
    }
    return [dictionary copy];
}
-(NSDictionary *)groupByKey:(NSString *) key {
    return [self groupUsingBlock:^(id obj) {
            return [obj valueForKey:key];
        }];
}

Context

StackExchange Code Review Q#39690, answer score: 2

Revisions (0)

No revisions yet.