NSArray+Functional.m 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  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. - (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)sortedUsingSelector:(SEL)selector {
  71. if (FLEXArrayClassIsMutable(self)) {
  72. NSMutableArray *me = (id)self;
  73. [me sortUsingSelector:selector];
  74. return me;
  75. } else {
  76. return [self sortedArrayUsingSelector:selector];
  77. }
  78. }
  79. @end