Created
November 19, 2021 10:07
-
-
Save Ceroce/13ed32d8e591c9514a211fb860a11765 to your computer and use it in GitHub Desktop.
Category on NSArray to add functional operators
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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