经常用swift的,会用到数组的一些高级运算符,比如map,flatmap,filter等,对数组的操作十分的友好,切换到swift时,通常会对NSArray的遍历,筛选等操作耽误功夫,因此想到把swift的操作符,在OC上进行改写。并增加结构联想,增加开发效率。
最终,希望实现的效果是这样子:
NSArray<NSNumber *> * test = @[@1,@2,@3,@4,@5];
//test map:<#^id _Nonnull(NSNumber * _Nonnull obj)transform#>
NSArray<NSString *> *aftermap = [test map:^id _Nonnull(NSNumber * _Nonnull obj) {
return [NSString stringWithFormat:@"%@", obj];
}];
NSArray<NSString *> *afterflatmap = [aftermap flatMap:^id _Nonnull(NSString * _Nonnull element) {
return @[element, element, element];
}];
NSArray<NSString *> *afterfilter = [afterflatmap filter:^BOOL(NSString * _Nonnull obj) {
return obj.integerValue > 3;
}];
NSArray<NSString *> *afterRemove = [afterfilter removeObjectsWhere:^BOOL(NSString * _Nonnull obj) {
return obj.integerValue == 5;
}];
//输出: aftermap:1,2,3,4,5
//输出: afterflatmap:1,1,1,2,2,2,3,3,3,4,4,4,5,5,5
//输出: afterfilter:4,4,4,5,5,5
//输出: afterRemove: 4,4,4
闲话不说,上代码
首先是NSArray+Monad.h文件
// 这里使用ObjectType的好处是,Xcode可以根据上文的类型,自动推断block中的类型,
// 减少编译时的误差,和自己转换格式的过程
@interface NSArray<ObjectType> (Monad)
- (NSArray*)map:(id(^)(ObjectType obj))transform;
- (NSArray<ObjectType>*)filter:(BOOL(^)(ObjectType obj))includeElement;
- (_Nullable ObjectType)first:(BOOL(^)(ObjectType obj))includeElement;
- (NSArray*)flatMap:(id (^)(ObjectType element))block;
- (NSInteger)firstIndexWhere:(BOOL(^)(ObjectType obj))includeElement;
- (NSArray<ObjectType>*)removeObjectsWhere:(BOOL(^)(ObjectType obj))includeElement;
@end
然后是实现文件。
@implementation NSArray (Monad)
- (NSArray*)map:(id(^)(id))transform {
NSMutableArray *array = [[NSMutableArray alloc] init];
for (id _Nonnull obj in self) {
[array addObject:transform(obj)];
}
return array;
}
- (NSArray*)filter:(BOOL(^)(id))includeElement {
NSMutableArray *array = [[NSMutableArray alloc] init];
[self enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if (includeElement(obj)) {
[array addObject:obj];
}
}];
return array;
}
- (NSArray*)removeObjectsWhere:(BOOL(^)(id))includeElement {
NSMutableArray *array = [NSMutableArray arrayWithCapacity:0];
for (id _Nonnull obj in self) {
if (!includeElement(obj)) {
[array addObject:obj];
}
}
return array;
}
- (NSArray *)flatMap:(id (^)(id element))block {
NSMutableArray *result = [NSMutableArray array];
for (id element in self) {
id flatElement = block(element);
if ([flatElement isKindOfClass:[NSArray class]]) {
[result addObjectsFromArray:flatElement];
} else if (flatElement){
[result addObject:flatElement];
} else {
continue;
}
}
return [result copy];
}
- (_Nullable id)first:(BOOL(^)(id obj))includeElement {
for (id _Nonnull obj in self) {
if (includeElement(obj)) {
return obj;
}
}
return nil;
}
- (NSInteger)firstIndexWhere:(BOOL(^)(id obj))includeElement {
for (int i = 0; i < self.count; i ++) {
id ob = self[i];
if (includeElement(ob)) {
return i;
}
}
return -1;
}
@end