#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSArray<ObjectType> (Block)
/**
遍歷數(shù)組
@param body 遍歷操作 block
*/
- (void)forEach:(void (^)(ObjectType obj))body;
/**
根據(jù)篩選條件篩選數(shù)組元素。如:
NSArray <NSNumber*>*nums = @[@1, @2, @3, @4, @5];
NSArray <NSNumber*>*evens = [nums select:^BOOL(NSNumber *obj){
return [obj integerValue] % 2 == 0;
}]; // evens is [2, 4]
@param where 篩選條件
@return 篩選后的新數(shù)組
*/
- (nullable NSArray <ObjectType>*)select:(BOOL (^)(ObjectType obj))where;
/**
按照順序遍歷的方式育八,根據(jù)篩選條件篩選出第一個(gè)符合條件的數(shù)組元素迫靖。
@param where 篩選條件
@return 選擇的元素
*/
- (nullable ObjectType)selectOne:(BOOL (^)(ObjectType obj))where;
/**
select 的相反操作既峡,根據(jù)指定條件從數(shù)組中剔除元素乡翅。
@param where 剔除條件
@return 剔除指定的元素后的數(shù)組
*/
- (nullable NSArray <ObjectType>*)reject:(BOOL (^)(ObjectType obj))where;
/**
重組元素
@param initial 初始值
@param body 重組 block
@return 組合完成后的結(jié)果
*/
- (id)reduce:(id)initial body:(id (^)(id result, ObjectType obj))body;
/**
將數(shù)組元素映射成另外一種類(lèi)型的元素并包裝成新數(shù)組珠插。
注意奴迅,如果返回 nil材义,則對(duì)應(yīng)的元素會(huì)被忽略均抽。
@param body 映射邏輯 block
@return 映射完成后的新數(shù)組
*/
- (NSArray *)flatMap:(nullable id (^)(ObjectType obj))body;
/**
數(shù)組中是否包含符合指定條件的元素
@param where 指定條件
@return 包含返回 YES, 否則返回 NO.
*/
- (BOOL)contain:(BOOL (^)(ObjectType obj))where;
@end
@interface NSArray<ObjectType> (Safe)
- (ObjectType)safe_objectAtIndex:(NSUInteger)index;
@end
@interface NSArray<ObjectType> (Select)
/**
獲取數(shù)組組合結(jié)果。從給定的數(shù)組中選擇 n 個(gè)元素的組合(無(wú)順序)其掂。
@param count 指定選擇的個(gè)數(shù)
@return 結(jié)果集合
*/
- (NSArray <NSArray<ObjectType>*>*)combineWithCount:(NSUInteger)count;
/**
隨機(jī)打亂數(shù)組的順序
@return 亂序后的數(shù)組
*/
- (NSArray <ObjectType>*)random;
@end
#import "NSArray+Block.h"
@implementation NSArray (Block)
- (void)forEach:(void (^)(id))body
{
for (id element in self) {
body(element);
}
}
- (NSArray <id>*)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 <id>*)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 遞歸調(diào)用循環(huán)引用
__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