【转载加链接,谢谢合作!】
[2021/01/09 06:40] 新增字符串高阶函数;
[2020/07/07 09:22] 默认 block 返回值不为空,用户可以灵活传入各种类型默认值;
[2020/07/03 14:22] 增添 covariant(协变性)支持;
[2020/06/08 18:01] 优化数组高阶函数,通用性扩展;
需求逻辑 =》函数/方法 =》通用函数/方法 =》高阶函数
对特定需求逻辑实现为函数/方法,对相似需求逻辑进行抽象为通用函数/方法,对通用函数/方法进行二次抽象为高阶函数,可以理解为函数的抽象函数。本质上并不复杂,关键是要彻底想透每一个细节,任何一个参数类型都会极大的影响其适用性。(抽象层次越高,适用范围越广,具体使用越复杂[可通过语言层面例如泛型进行优化],函数封装需要同时兼顾适用性和使用便利性。)
NSArray 高阶函数:
NS_ASSUME_NONNULL_BEGIN
@interface NSArray<ObjectType> (Helper)
///componentsJoinedByString
@property(nonatomic, strong, readonly) NSString *(^joinedBy)(NSString *);
/**
map 高阶函数(使用时需要将obj强转为数组元素类型)
*/
- (NSArray *)map:(id (NS_NOESCAPE ^)(ObjectType obj, NSUInteger idx))block;
/**
forEach 高阶函数
*/
- (void)forEach:(id (NS_NOESCAPE ^)(ObjectType obj, NSUInteger idx))block;
/**
compactMap 高阶降维函数
*/
- (NSArray *)compactMap:(id (NS_NOESCAPE ^)(ObjectType obj, NSUInteger idx))transform;
/**
filter 高阶函数(使用时需要将obj强转为数组元素类型)
*/
- (NSArray *)filter:(BOOL(NS_NOESCAPE ^)(ObjectType obj, NSUInteger idx))block;
/**
reduce 高阶函数(求和,累加等)
*/
- (NSNumber *)reduce:(NSNumber *)initial block:(NSNumber *(NS_NOESCAPE ^)(NSNumber *result, NSNumber *obj))block;
@end
@implementation NSArray (Helper)
- (NSString *(^)(NSString *))joinedBy{
return ^(NSString *value) {
return [self componentsJoinedByString: value];
};
}
- (NSArray *)map:(id (NS_NOESCAPE ^)(id obj, NSUInteger idx))block{
if (!block) {
NSParameterAssert(block != nil);
return self;
}
__block NSMutableArray *marr = [NSMutableArray array];
[self enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
id value = block(obj, idx);
if (value) {
[marr addObject:value];
}
}];
// DDLog(@"%@->%@", self, marr.copy);
return marr.copy;
}
- (void)forEach:(id (NS_NOESCAPE ^)(id obj, NSUInteger idx))block{
if (!block) {
return;
}
[self enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
block(obj, idx);
}];
}
- (NSArray *)compactMap:(id (NS_NOESCAPE ^)(id obj, NSUInteger idx))block{
if (!block) {
NSParameterAssert(block != nil);
return self;
}
__block NSMutableArray *marr = [NSMutableArray array];
[self enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
id value = block(obj, idx);
if ([value isKindOfClass:NSArray.class]) {
[marr addObjectsFromArray:value];
} else {
[marr addObject:value];
}
}];
// DDLog(@"%@->%@", self, marr.copy);
return marr.copy;
}
- (NSArray *)filter:(BOOL(NS_NOESCAPE ^)(id obj, NSUInteger idx))block{
if (!block) {
NSParameterAssert(block != nil);
return self;
}
__block NSMutableArray *marr = [NSMutableArray array];
[self enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if (block(obj, idx) == true) {
[marr addObject:obj];
}
}];
return marr.copy;
}
- (NSNumber *)reduce:(NSNumber *)initial block:(NSNumber *(NS_NOESCAPE ^)(NSNumber *result, NSNumber *obj))block{
if (!block) {
NSParameterAssert(block != nil);
return initial;
}
__block NSNumber *value = initial;
[self enumerateObjectsUsingBlock:^(NSNumber *_Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
value = block(value, obj);
}];
return value;
}
@end
🌰🌰🌰:
1. 截取子字符串
NSArray<NSString *> *list = @[@"1111", @"2222", @"3333", @"4444"];
NSArray *listOne = [list map:^id * _Nonnull(NSString * _Nonnull obj, NSUInteger idx) {
return [obj substringToIndex:idx];
}];
// listOne_(, 2, 33, 444,)
2. 抽取模型数组对应属性(值为nil则返回对应模型)
NSMutableArray * marr = [NSMutableArray array];
for (NSInteger i = 0; i < 5; i++) {
WHKNetInfoFeedModel * model = [[WHKNetInfoFeedModel alloc]init];
model.category = [NSString stringWithFormat:@"name_%@", @(i)];
model.vendor = [NSDateFormatter stringFromDate:NSDate.date format:kFormatDate];
[marr addObject:model];
}
NSArray *listTwo = [marr map:^id * _Nonnull(id _Nonnull obj, NSUInteger idx) {
return [obj valueForKey:@"category"] ? : @"";
}];
// listTwo_( name_0, name_1, name_2, name_3, name_4, )
3.修改数组模型属性值
NSArray *listThree = [marr map:^id * _Nonnull(NSObject * _Nonnull obj, NSUInteger idx) {
[obj setValue:@(idx) forKey:@"category"];
return obj;
}];
// listThree_(model.category = @(0), model.category = @(1), model.category = @(2), model.category = @(3), model.category = @(4));
4. 过滤大约@“222”的元素
NSArray *listTwo = [list filter:^BOOL(id * _Nonnull obj, NSUInteger idx) {
return [(NSString *)obj compare:@"222" options:NSNumericSearch] == NSOrderedDescending;
}];
// listTwo_( 333, 444, )
5. 过滤不等于@“222”的元素
NSArray *list2 = [list filter:^BOOL(id * _Nonnull obj, NSUInteger idx) {
return (![(NSString *)obj isEqualToString:@"222"]);
}];
// list2_(111,333,444,)
6. array = @[@1, @3, @5, @7, @9];
NSNumber *result = [array reduce:@(0) block:^NSNumber * _Nonnull(NSNumber * _Nonnull result, NSNumber * _Nonnull obj) {
return @(num1.floatValue * 10 + num2.floatValue);
}];
// result_13579
NSNumber *result1 = [array reduce:@(0) block:^NSNumber * _Nonnull(NSNumber * _Nonnull result, NSNumber * _Nonnull obj) {
return @(num1.floatValue + num2.floatValue);
}];
// result1_25
NSDictionary 高阶函数:
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSDictionary<KeyType, ObjectType> (Helper)
/**
map 高阶函数
*/
- (NSDictionary *)map:(NSDictionary *(NS_NOESCAPE ^)(KeyType key, ObjectType obj))block;
/**
forEach 高阶函数
*/
- (void)forEach:(NSDictionary* (NS_NOESCAPE ^)(KeyType key, ObjectType obj))block;
/**
filter 高阶函数
*/
- (NSDictionary *)filter:(BOOL (NS_NOESCAPE ^)(KeyType key, ObjectType obj))block;
/**
compactMapValues 高阶函数
*/
- (NSDictionary *)compactMapValues:(id (NS_NOESCAPE ^)(ObjectType obj))block;
/**
merge 高阶函数
*/
- (NSDictionary *)merge:(NSDictionary *)dictionary block:(id(^)(KeyType key, ObjectType oldVal, _Nullable ObjectType newVal))block;
@end
@implementation NSDictionary(Tmp)
- (NSDictionary *)map:(NSDictionary *(NS_NOESCAPE ^)(id key, id obj))block{
if (!block) {
NSParameterAssert(block != nil);
return self;
}
__block NSMutableDictionary *mdic = [NSMutableDictionary dictionary];
[self enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
NSDictionary *value = block(key, obj);
if (value) {
[mdic addEntriesFromDictionary:value];
}
}];
return mdic.copy;
}
- (void)forEach:(NSDictionary *(NS_NOESCAPE ^)(id key, id obj))block{
if (!block) {
return;
}
[self enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
block(key, obj);
}];
}
- (NSDictionary *)filter:(BOOL (NS_NOESCAPE ^)(id key, id obj))block{
if (!block) {
NSParameterAssert(block != nil);
return self;
}
__block NSMutableDictionary *mdic = [NSMutableDictionary dictionary];
[self enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
if (block(key, obj) == true) {
mdic[key] = obj;
}
}];
return mdic.copy;
}
- (NSDictionary *)compactMapValues:(id (NS_NOESCAPE ^)(id obj))block{
if (!block) {
NSParameterAssert(block != nil);
return self;
}
__block NSMutableDictionary *mdic = [NSMutableDictionary dictionary];
[self enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
id value = block(obj);
if (value) {
mdic[key] = value;
}
}];
return mdic.copy;
}
- (NSDictionary *)merge:(NSDictionary *)dictionary block:(id(^)(id key, id oldVal, id newVal))block {
NSMutableDictionary *mdic = [NSMutableDictionary dictionary];
if (!block) {
[mdic addEntriesFromDictionary:self];
[mdic addEntriesFromDictionary:dictionary];
return mdic.copy;
}
[mdic addEntriesFromDictionary:self];
[dictionary enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
id oldVal = [self.allKeys containsObject:key] ? self[key] : nil;
id value = block(key, oldVal, obj);
if (value) {
[mdic setObject:value forKey:key];
}
}];
return mdic.copy;
}
@end
🌰🌰🌰:
- (void)funtionMoreDic{
NSDictionary<NSString *, NSString *> *dic = @{
@"1": @"111",
@"2": @"222",
@"3": @"222",
@"4": @"444",
};
NSDictionary *dic1 = [dic map:^NSDictionary * _Nonnull(NSString * _Nonnull key, NSString * _Nonnull obj) {
return @{[key stringByAppendingFormat:@"%@", @"_"] : [obj stringByAppendingFormat:@"%@", @"_"],
};
}];
DDLog(@"dic1_%@",dic1);
// 2020-07-03 06:20:05.248000+0000【line -305】-[TestViewController funtionMoreDic] dic1_{
// 2_ = 222_;
// 4_ = 444_;
// 1_ = 111_;
// 3_ = 222_;
// }
NSDictionary *dic2 = [dic compactMapValues:^id _Nonnull(NSString * _Nonnull obj) {
return [NSString stringWithFormat:@"%@_", obj];
}];
DDLog(@"dic2_%@",dic2);
// 2019-08-26 18:54:36.503000+0800【line -303】-[TestViewController funtionMoreDic] dic1_{
// 3 = 222_;
// 1 = 111_;
// 4 = 444_;
// 2 = 222_;
// }
NSDictionary *dic3 = [dic filter:^BOOL(NSString * _Nonnull key, NSString * _Nonnull obj) {
return [key isEqualToString:@"2"];
}];
DDLog(@"dic3_%@",dic3);
// 2019-08-26 18:54:36.504000+0800【line -304】-[TestViewController funtionMoreDic] dic2_{
// 2 = 222;
// }
NSDictionary *dic4 = [dic filter:^BOOL(NSString * _Nonnull key, NSString * _Nonnull obj) {
return [obj isEqualToString:@"222"];
}];
DDLog(@"dic4_%@",dic4);
// 2019-08-26 18:54:36.504000+0800【line -305】-[TestViewController funtionMoreDic] dic3_{
// 3 = 222;
// 2 = 222;
// }
}
@interface NSString (Ext)
- (NSArray<NSString *> *(^)(NSString *))separatedBy;
///separator 分割后的子元素进行转换("1,2,3,4" -> "1,4,9,16")
- (NSString *)mapBySeparator:(NSString *)separator transform:(NSString * (NS_NOESCAPE ^)(NSString *obj))transform;
@end
@implementation NSString (Ext)
(NSArray<NSString *> *(^)(NSString *))separatedBy{
return ^(NSString *value) {
return [self componentsSeparatedByString: value];
};
}
#pragma mark -高阶函数
- (NSString *)mapBySeparator:(NSString *)separator transform:(NSString * (NS_NOESCAPE ^)(NSString *obj))transform{
if (!transform) {
NSParameterAssert(transform != nil);
return self;
}
NSString *result = [self.separatedBy(separator) map:^id _Nonnull(NSString * _Nonnull obj, NSUInteger idx) {
return transform(obj);
}].joinedBy(separator);
return result;
}
@end
网友评论