起因
经常处理数据的时候 会遇到这样的问题。
看到其他语言如swift 或者python 都有自己的map filter 的语法,OC却要用for 语句
1.网络请求的数据,需要数组中第几个元素进行计算
2.需要满足部分的元素形成一个新的数组
一般关于这两个问题的反映是用for 数组 ,然后new 一个新的可变数组把符合条件的数据加入到数组中
NSMutableArray *marr = [NSMutableArray array];
for (int i = 0 ; i < array.count; i++) {
id temp = array[i];
if(temp 满足条件) {
[marr addobject:temp];
这个时候 得到了一个满足条件的数组
}
}
简单的还好,如果涉及很多需要满足条件的计算 ,这样的代码可读性和维护性,都非常的有挑战。
方案一
把for 的语句封装起来
方案二
添加NSArray的Category
*.h 文件
#import <Foundation/Foundation.h>
typedef BOOL(^filterCondition)(id target);
typedef id (^mapCondition)(id target);
@interface NSArray (Common)
- (NSArray *)reverse;
/// 筛选出所有符合条件的元素
/// @param condition 筛选条件
- (NSArray *)filter:(filterCondition)condition;
/// 筛选出前几个符合条件的元素
/// @param condition 筛选条件
/// @param count 需要的数量
- (NSArray *)filter:(filterCondition)condition theTopServeral:(NSUInteger)count;
/// 筛选出后几个符合条件的元素
/// @param condition 筛选条件
/// @param count 需要的数量
- (NSArray *)filter:(filterCondition)condition theEndServeral:(NSUInteger)count;
/// map遍历
- (NSArray *)map:(mapCondition)condition;
@end
*.m 文件
#import "NSArray+Common.h"
@implementation NSArray (Common)
- (NSArray *)reverse {
return [[[NSMutableArray arrayWithArray:self] reverseObjectEnumerator] allObjects];
}
- (NSArray *)filter:(filterCondition)condition {
return [self filter:condition needCount:self.count isTopSeveral:YES];
}
- (NSArray *)filter:(filterCondition)condition theTopServeral:(NSUInteger)count {
return [self filter:condition needCount:count isTopSeveral:YES];
}
- (NSArray *)filter:(filterCondition)condition theEndServeral:(NSUInteger)count {
return [self filter:condition needCount:count isTopSeveral:NO];
}
- (NSArray *)filter:(filterCondition)condition needCount:(NSUInteger)count isTopSeveral:(BOOL)isTopSeveral {
if (count < 1) {
return @[];
}
NSMutableArray *tmp = [NSMutableArray arrayWithCapacity:self.count];
[self enumerateObjectsWithOptions:isTopSeveral ? NSEnumerationConcurrent : NSEnumerationReverse usingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if (tmp.count >= count - 1) {
*stop = YES;
}
if (condition(obj)) {
[tmp addObject:obj];
}
}];
return tmp.copy;
}
- (NSArray *)map:(mapCondition)condition {
if (!self.count) {
return self;
}
NSMutableArray *tmp = [NSMutableArray arrayWithCapacity:self.count];
[self enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if (condition(obj)) {
[tmp addObject:condition(obj)];
} else {
#ifdef DEBUG
NSString *tipString = [NSString stringWithFormat:@"元素不符合遍历条件,index = %ld, 元素:%@", idx, obj];
NSAssert(NO, tipString);
#endif
}
}];
return tmp.copy;
}
@end
代码的核心 一句 就是enumerateObjectsUsingBlock
使用方法
这里的target 是id 类型,可以是网络请求下来的model ,也可以是字符串 int 等类型
直接返回 float
NSArray *arr = @[@"asd",@"bcd3",@"aew",@"zxc",@"123",@"567",@"bnj",@"opi",@"tytreu",@"qwerty",@"12"];
NSArray *sortArray = [arr filter:^BOOL(NSString * target) {
return target.length > 2;
}];
NSLog(@"print array - %@",sortArray);
NSArray *topSerArr = [arr filter:^BOOL(NSString * target) {
return target.length > 2;
} theTopServeral:4];
NSLog(@"print tio serveral array - %@",topSerArr);
通过block 的内部条件进行数据筛选,把筛选条件明确的展示在最显眼的位置
总结
这个优化虽然和小,但是一个大型项目恰恰是每一处的优化才带来整体的效率提升。