美文网首页iOS
重构:Objective-C 高阶函数实现/自定义

重构:Objective-C 高阶函数实现/自定义

作者: SoaringHeart | 来源:发表于2019-08-15 17:26 被阅读0次

【转载加链接,谢谢合作!】

[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

Swift 泛型函数自定义

相关文章

  • 重构:Objective-C 高阶函数实现/自定义

    【转载加链接,谢谢合作!】 [2021/01/09 06:40] 新增字符串高阶函数;[2020/07/07 09...

  • python学习(三)函数式编程

    高阶函数 函数也是变量,函数参数为函数的函数,称作高阶函数 自定义高阶函数 内建高阶函数 map/reducema...

  • 六,Kotlin自定义高阶函数

    1,自定义高阶函数接收一个函数类型的参数 定义高阶函数,传入两个参数,传入一个函数,函数结果抽象,来实现他们不同的...

  • python学习笔记

    高阶函数:将函数作为参数 sortted()它还可以接收一个key函数来实现自定义的排序,reversec参数可反...

  • 18. sorted

    sorted()函数也是一个高阶函数,它还可以接收一个key函数来实现自定义的排序,例如按绝对值大小排序:>>> ...

  • Python函数和高阶函数

    函数(基础、高阶函数(实参高阶函数、返回值高阶、装饰器)) 1.函数就是实现某一特定功能的代码块 2.定义函数(创...

  • swift中高阶函数map、flatMap、filter、red

    swift中高阶函数map、flatMap、filter、reduce Swift相比于Objective-C又一...

  • 【原】Python学习笔记——进阶篇

    python的高阶函数 一个函数作为另外一个函数的参数、map()、reduce()、filter()、自定义排序...

  • swift-sequence 序列

    swift下有许多的高阶函数如:map 重对应的一个类型映射到另一个类型的整合函数 这样就可以实现对自定义对象

  • python2

    sorted()也是一个高阶函数。用sorted()排序的关键在于实现一个映射函数。 函数作为返回值 高阶函数除了...

网友评论

    本文标题:重构:Objective-C 高阶函数实现/自定义

    本文链接:https://www.haomeiwen.com/subject/nsxtsctx.html