Skip to content

Instantly share code, notes, and snippets.

@Ceroce
Created November 19, 2021 10:07
Show Gist options
  • Save Ceroce/13ed32d8e591c9514a211fb860a11765 to your computer and use it in GitHub Desktop.
Save Ceroce/13ed32d8e591c9514a211fb860a11765 to your computer and use it in GitHub Desktop.
Category on NSArray to add functional operators
#import <Foundation/Foundation.h>
@interface NSArray (Functional)
-(NSArray *) dropFirst;
-(NSArray *) dropLast;
-(NSArray *) map:(id (^)(id element))closure;
-(id) reduceWithInitial:(id)initial partial:(id (^)(id acc, id element))partial;
-(NSArray *) filter:(BOOL (^)(id element))shouldKeep;
@end
#import "NSArray+Functional.h"
@implementation NSArray (Functional)
-(NSArray *) dropFirst {
if(self.count == 0) {
return @[];
}
return [self subarrayWithRange:NSMakeRange(1, self.count-1)];
}
-(NSArray *)dropLast {
if(self.count == 0) {
return @[];
}
return [self subarrayWithRange:NSMakeRange(0, self.count-1)];
}
-(NSArray *) map:(id (^)(id))closure {
NSMutableArray *mutable = [NSMutableArray arrayWithCapacity:self.count];
for (id element in self) {
[mutable addObject:closure(element)];
}
return mutable;
}
-(id) reduceWithInitial:(id)initial partial:(id (^)(id acc, id element))partial {
id acc = initial;
for (id element in self) {
acc = partial(acc, element);
}
return acc;
}
-(NSArray *) filter:(BOOL (^)(id element))shouldKeep {
NSMutableArray *mutable = [NSMutableArray arrayWithCapacity:self.count];
for (id element in self) {
if(shouldKeep(element)) {
[mutable addObject:element];
}
}
return mutable;
}
@end
#import <XCTest/XCTest.h>
#import "NSArray+Functional.h"
@interface NSArrayFunctionalTests : XCTestCase
@end
@implementation NSArrayFunctionalTests
// MARK: dropFirst
-(void) testDropFirstOnEmptyArray {
XCTAssertEqualObjects([[NSArray array] dropFirst], @[]);
}
-(void) testDropFirstOnOneElementArray {
NSArray *oneElementArray = @[@"one"];
XCTAssertEqualObjects([oneElementArray dropFirst], @[]);
}
-(void) testDropFirst {
NSArray *strings = @[@"one", @"two", @"three"];
NSArray *expected = @[@"two", @"three"];
XCTAssertEqualObjects([strings dropFirst], expected);
}
// MARK: dropLast
-(void) testDropLastOnEmptyArray {
XCTAssertEqualObjects([[NSArray array] dropLast], @[]);
}
-(void) testDropLastOnOneElementArray {
NSArray *oneElementArray = @[@"one"];
XCTAssertEqualObjects([oneElementArray dropLast], @[]);
}
-(void) testDropLast {
NSArray *strings = @[@"one", @"two", @"three"];
NSArray *expected = @[@"one", @"two"];
XCTAssertEqualObjects([strings dropLast], expected);
}
// MARK: map
-(void) testMapStrings {
NSArray *strings = @[@"one", @"two", @"three"];
NSArray *mappedStrings = [strings map:^id (NSString *obj) {
return [obj uppercaseString];
}];
NSArray *expected = @[@"ONE", @"TWO", @"THREE"];
XCTAssertEqualObjects(mappedStrings, expected);
}
// MARK: reduce
-(void) testReduceNumbers {
NSArray *numbers = @[@(1), @(2), @(3)];
NSArray *sum = [numbers reduceWithInitial:@(0) partial:^id(id acc, id element) {
return [NSNumber numberWithInteger:([acc integerValue] + [element integerValue])];
}];
XCTAssertEqualObjects(sum, @(6));
}
-(void) testReduceStrings {
NSArray *strings = @[@"one", @"two", @"three"];
NSArray *concatenation = [[strings dropFirst] reduceWithInitial:strings.firstObject partial:^id(NSString *acc, NSString *element) {
return [acc stringByAppendingFormat:@" %@", element];
}];
XCTAssertEqualObjects(concatenation, @"one two three");
}
// MARK: filter
-(void) testFiltersNumbers {
NSArray *numbers = @[@(1), @(2), @(3), @(4), @(5), @(6), @(7), @(8)];
NSArray *evenNumbers = [numbers filter:^BOOL(NSNumber *number) {
return [number integerValue] % 2 == 0;
}];
NSArray *expectedNumbers = @[@(2), @(4), @(6), @(8)];
XCTAssertEqualObjects(evenNumbers, expectedNumbers);
}
-(void) testFiltersStrings {
NSArray *nouns = @[@"apple", @"cars", @"toys", @"skin"];
NSArray *plurals = [nouns filter:^BOOL(NSString *noun) {
return [noun hasSuffix:@"s"];
}];
NSArray *expected = @[@"cars", @"toys"];
XCTAssertEqualObjects(plurals, expected);
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment