NSArray+Block

#import 

NS_ASSUME_NONNULL_BEGIN
@interface NSArray (Block)

/**
 遍历数组

 @param body 遍历操作 block
 */
- (void)forEach:(void (^)(ObjectType obj))body;

/**
 根据筛选条件筛选数组元素。如:
 
 NSArray *nums  = @[@1, @2, @3, @4, @5];
 NSArray *evens = [nums select:^BOOL(NSNumber *obj){
    return [obj integerValue] % 2 == 0;
 }];    // evens is [2, 4]

 @param where 筛选条件
 @return 筛选后的新数组
 */
- (nullable NSArray *)select:(BOOL (^)(ObjectType obj))where;

/**
 按照顺序遍历的方式,根据筛选条件筛选出第一个符合条件的数组元素。

 @param where 筛选条件
 @return 选择的元素
 */
- (nullable ObjectType)selectOne:(BOOL (^)(ObjectType obj))where;

/**
 select 的相反操作,根据指定条件从数组中剔除元素。

 @param where 剔除条件
 @return 剔除指定的元素后的数组
 */
- (nullable NSArray *)reject:(BOOL (^)(ObjectType obj))where;

/**
 重组元素

 @param initial 初始值
 @param body 重组 block
 @return 组合完成后的结果
 */
- (id)reduce:(id)initial body:(id (^)(id result, ObjectType obj))body;

/**
 将数组元素映射成另外一种类型的元素并包装成新数组。
 注意,如果返回 nil,则对应的元素会被忽略。

 @param body 映射逻辑 block
 @return 映射完成后的新数组
 */
- (NSArray *)flatMap:(nullable id (^)(ObjectType obj))body;

/**
 数组中是否包含符合指定条件的元素

 @param where 指定条件
 @return 包含返回 YES, 否则返回 NO.
 */
- (BOOL)contain:(BOOL (^)(ObjectType obj))where;

@end



@interface NSArray (Safe)

- (ObjectType)safe_objectAtIndex:(NSUInteger)index;

@end

@interface NSArray (Select)

/**
 获取数组组合结果。从给定的数组中选择 n 个元素的组合(无顺序)。
 @param count 指定选择的个数
 @return 结果集合
 */
- (NSArray *>*)combineWithCount:(NSUInteger)count;

/**
 随机打乱数组的顺序

 @return 乱序后的数组
 */
- (NSArray *)random;

@end
#import "NSArray+Block.h"

@implementation NSArray (Block)

- (void)forEach:(void (^)(id))body
{
    for (id element in self) {
        body(element);
    }
}

- (NSArray *)select:(BOOL (^)(id))where
{
    __block NSArray *array = @[];
    [self enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        if (where(obj)) {
            array = [array arrayByAddingObject:obj];
        }
    }];
    if (array.count == 0)
        return nil;
    return array;
}

- (nullable id)selectOne:(BOOL (^)(id obj))where {
    __block id selectedObj = nil;
    [self enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        if (where(obj)) {
            selectedObj = obj;
            *stop = YES;
        }
    }];
    return selectedObj;
}

- (NSArray *)reject:(BOOL (^)(id))where
{
    return [self select:^BOOL(id obj) {
        return !where(obj);
    }];
}

- (id)reduce:(id)initial body:(id (^)(id, id))body
{
    NSParameterAssert(body != nil);
    
    __block id result = initial;
    
    [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        result = body(result, obj);
    }];
    
    return result;
}

- (NSArray *)flatMap:(id _Nullable (^)(id _Nonnull))body
{
    NSParameterAssert(body != nil);
    
    NSMutableArray *result = [NSMutableArray arrayWithCapacity:self.count];
    
    [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        id value = body(obj);
        if (value) [result addObject:value];
    }];
    
    return [result copy];
}

- (BOOL)contain:(BOOL (^)(id))where {
    
    __block BOOL res = NO;
    [self enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        if (where(obj)) {
            *stop = YES;
            res = YES;
        }
    }];
    
    return res;
}

@end





@implementation NSArray (Safe)

- (id)safe_objectAtIndex:(NSUInteger)index {
    index = MIN(index, self.count - 1);
    return [self objectAtIndex:index];
}

@end



@implementation NSArray (Select)

- (NSArray *)combineWithCount:(NSUInteger)count {
    
    NSMutableArray *array = [NSMutableArray arrayWithCapacity:count];
    NSMutableArray *res = [NSMutableArray array];
    
    // 防止 block 递归调用循环引用
    __block void (^combine)(NSUInteger, NSUInteger, NSUInteger);
    __block __weak void (^weakCombine)(NSUInteger, NSUInteger, NSUInteger);
    
    weakCombine = combine = ^(NSUInteger count, NSUInteger begin, NSUInteger index) {
        if (count == 0) { [res addObject:array.copy]; return; }
        
        for (NSUInteger i = begin; i < self.count; ++i) {
            array[index] = self[i];
            weakCombine(count - 1, i + 1, index + 1);
        }
    };
    combine(count, 0, 0);
    return [res copy];
}

- (NSArray *)random {
    return [self sortedArrayUsingComparator:^NSComparisonResult(id  _Nonnull obj1, id  _Nonnull obj2) {
        return arc4random() % 2 == 0 ? NSOrderedAscending : NSOrderedDescending;
    }];
}

@end

你可能感兴趣的:(NSArray+Block)