diff --git a/Classes/NSArray+ObjectiveSugar.h b/Classes/NSArray+ObjectiveSugar.h index 2562eb1..aef04d2 100644 --- a/Classes/NSArray+ObjectiveSugar.h +++ b/Classes/NSArray+ObjectiveSugar.h @@ -152,6 +152,14 @@ */ - (NSArray *)reject:(BOOL (^)(id object))block; +/** + Iterate through current array adding the element to a dictionary asking which key to use. + + @param A block that returns the key that should be used to add the element to the dictionary + @return A dictionary with the elements grouped by the key + */ +- (NSDictionary *)groupBy:(id (^)(id object))key; + /** Recurse through self checking for NSArrays and extract all elements into one single array diff --git a/Classes/NSArray+ObjectiveSugar.m b/Classes/NSArray+ObjectiveSugar.m index 82c28f5..d86372e 100644 --- a/Classes/NSArray+ObjectiveSugar.m +++ b/Classes/NSArray+ObjectiveSugar.m @@ -114,6 +114,17 @@ - (NSArray *)reject:(BOOL (^)(id object))block { }]]; } +- (NSDictionary *)groupBy:(id (^)(id object))key { + return [self reduce:[NSMutableDictionary dictionary] withBlock:^id(NSMutableDictionary *accumulator, id object) { + if (!accumulator[key(object)]) { + accumulator[key(object)] = [NSMutableArray array]; + } + [accumulator[key(object)] addObject:object]; + return accumulator; + }]; +} + + - (id)detect:(BOOL (^)(id object))block { for (id object in self) { if (block(object)) diff --git a/Example/ObjectiveSugarTests/NSArrayTests.m b/Example/ObjectiveSugarTests/NSArrayTests.m index 651d474..b24ae3d 100644 --- a/Example/ObjectiveSugarTests/NSArrayTests.m +++ b/Example/ObjectiveSugarTests/NSArrayTests.m @@ -145,6 +145,16 @@ return @(accumulator.intValue + numbah.intValue); }] should] equal:@60]; }); + + it(@"-groupBy: returns a dictionary grouped with the specified keys", ^{ + NSDictionary *groupedByPairs = [oneToTen groupBy:^id(NSNumber *number) { + return @([number intValue] % 2 == 0); + }]; + [[groupedByPairs[@YES] should] containObjects:@2, @4, @6, @8, @10, nil]; + [[groupedByPairs[@YES] shouldNot] containObjects:@1, @3, @5, @7, @9, nil]; + [[groupedByPairs[@NO] should] containObjects:@1, @3, @5, @7, @9, nil]; + [[groupedByPairs[@NO] shouldNot] containObjects:@2, @4, @6, @8, @10, nil]; + }); it(@"-unique produces a duplicate-free array", ^{ NSArray *arrayWithDuplicates = @[@1, @1, @"something", @"something"]; diff --git a/Example/ObjectiveSugarTests/NSStringTests.m b/Example/ObjectiveSugarTests/NSStringTests.m index df96cd8..245c744 100644 --- a/Example/ObjectiveSugarTests/NSStringTests.m +++ b/Example/ObjectiveSugarTests/NSStringTests.m @@ -15,7 +15,7 @@ it(@"NSStringWithFormat makes NSString -stringWithFormat", ^{ - [[NSStringWithFormat(@"This is %@", @1) should] equal:@"This is 1"]; + [[[NSString stringWithFormat:@"This is %@", @1] should] equal:@"This is 1"]; }); }); @@ -55,14 +55,14 @@ context(@"lowerCamelCase", ^{ it(@"converts snake_case to snakeCase", ^{ - [[[@"snake_case" lowerCamelCase] should] equal:@"snakeCase"] + [[[@"snake_case" lowerCamelCase] should] equal:@"snakeCase"]; }); it(@"handles extraneous underscores", ^{ - [[[@"_snake_case" lowerCamelCase] should] equal:@"snakeCase"] - [[[@"snake_case_" lowerCamelCase] should] equal:@"snakeCase"] + [[[@"_snake_case" lowerCamelCase] should] equal:@"snakeCase"]; + [[[@"snake_case_" lowerCamelCase] should] equal:@"snakeCase"]; }); - } + }); it(@"-strip strips whitespaces and newlines from both ends", ^{ [[[@"\n Look mo, no empties!\n \n\n " strip] should] equal:@"Look mo, no empties!"]; diff --git a/README.md b/README.md index f7fa44c..197b333 100644 --- a/README.md +++ b/README.md @@ -166,6 +166,13 @@ numbers[range]; [numbers reverse]; // [@6, @5, @4, @3, @2, @1] +// group pair numbers +[numbers groupBy:^id(NSNumber *number) { + return @([number intValue] % 2 == 0); +}]; +// @{@NO : @[@1, @3, @5], +// @YES : @[@2, @4, @6]} + NSArray *fruits = @[ @"banana", @"mango", @"apple", @"pear" ];