NSArray+FLEX.m 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. //
  2. // NSArray+FLEX.m
  3. // FLEX
  4. //
  5. // Created by Tanner Bennett on 9/25/19.
  6. // Copyright © 2020 FLEX Team. All rights reserved.
  7. //
  8. #import "NSArray+FLEX.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 new];
  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. - (instancetype)flex_subArrayUpto:(NSUInteger)maxLength {
  48. if (maxLength > self.count) {
  49. if (FLEXArrayClassIsMutable(self)) {
  50. return self.mutableCopy;
  51. }
  52. return self;
  53. }
  54. return [self subarrayWithRange:NSMakeRange(0, maxLength)];
  55. }
  56. + (__kindof NSArray *)flex_forEachUpTo:(NSUInteger)bound map:(id(^)(NSUInteger))block {
  57. NSMutableArray *array = [NSMutableArray new];
  58. for (NSUInteger i = 0; i < bound; i++) {
  59. id obj = block(i);
  60. if (obj) {
  61. [array addObject:obj];
  62. }
  63. }
  64. // For performance reasons, don't copy large arrays
  65. if (bound < 2048 && !FLEXArrayClassIsMutable(self)) {
  66. return array.copy;
  67. }
  68. return array;
  69. }
  70. + (instancetype)flex_mapped:(id<NSFastEnumeration>)collection block:(id(^)(id obj, NSUInteger idx))mapFunc {
  71. NSMutableArray *array = [NSMutableArray new];
  72. NSInteger idx = 0;
  73. for (id obj in collection) {
  74. id ret = mapFunc(obj, idx++);
  75. if (ret) {
  76. [array addObject:ret];
  77. }
  78. }
  79. // For performance reasons, don't copy large arrays
  80. if (array.count < 2048) {
  81. return array.copy;
  82. }
  83. return array;
  84. }
  85. - (instancetype)flex_sortedUsingSelector:(SEL)selector {
  86. if (FLEXArrayClassIsMutable(self)) {
  87. NSMutableArray *me = (id)self;
  88. [me sortUsingSelector:selector];
  89. return me;
  90. } else {
  91. return [self sortedArrayUsingSelector:selector];
  92. }
  93. }
  94. @end