NSArray+Functional.m 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. //
  2. // NSArray+Functional.m
  3. // FLEX
  4. //
  5. // Created by Tanner Bennett on 9/25/19.
  6. // Copyright © 2019 Flipboard. All rights reserved.
  7. //
  8. #import "NSArray+Functional.h"
  9. #define FLEXArrayClassIsMutable(me) ([[self class] isSubclassOfClass:[NSMutableArray class]])
  10. @implementation NSArray (Functional)
  11. - (__kindof NSArray *)flex_mapped:(id (^)(id, NSUInteger))mapFunc {
  12. NSMutableArray *map = [NSMutableArray new];
  13. [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
  14. id ret = mapFunc(obj, idx);
  15. if (ret) {
  16. [map addObject:ret];
  17. }
  18. }];
  19. if (self.count < 2048 && !FLEXArrayClassIsMutable(self)) {
  20. return map.copy;
  21. }
  22. return map;
  23. }
  24. - (__kindof NSArray *)flex_flatmapped:(NSArray *(^)(id, NSUInteger))block {
  25. NSMutableArray *array = [NSMutableArray array];
  26. [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
  27. NSArray *toAdd = block(obj, idx);
  28. if (toAdd) {
  29. [array addObjectsFromArray:toAdd];
  30. }
  31. }];
  32. if (array.count < 2048 && !FLEXArrayClassIsMutable(self)) {
  33. return array.copy;
  34. }
  35. return array;
  36. }
  37. - (NSArray *)flex_filtered:(BOOL (^)(id, NSUInteger))filterFunc {
  38. return [self flex_mapped:^id(id obj, NSUInteger idx) {
  39. return filterFunc(obj, idx) ? obj : nil;
  40. }];
  41. }
  42. - (void)flex_forEach:(void(^)(id, NSUInteger))block {
  43. [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
  44. block(obj, idx);
  45. }];
  46. }
  47. + (__kindof NSArray *)flex_forEachUpTo:(NSUInteger)bound map:(id(^)(NSUInteger))block {
  48. NSMutableArray *array = [NSMutableArray new];
  49. for (NSUInteger i = 0; i < bound; i++) {
  50. id obj = block(i);
  51. if (obj) {
  52. [array addObject:obj];
  53. }
  54. }
  55. // For performance reasons, don't copy large arrays
  56. if (bound < 2048 && !FLEXArrayClassIsMutable(self)) {
  57. return array.copy;
  58. }
  59. return array;
  60. }
  61. - (instancetype)sortedUsingSelector:(SEL)selector {
  62. if (FLEXArrayClassIsMutable(self)) {
  63. NSMutableArray *me = (id)self;
  64. [me sortUsingSelector:selector];
  65. return me;
  66. } else {
  67. return [self sortedArrayUsingSelector:selector];
  68. }
  69. }
  70. @end