给你一个嵌套的 NSArray 数据,实现一个迭代器类,该类提供一个 next() 方法,可以依次的取出这个 NSArray 中的数据。 比如 NSArray 如果是 [1,[4,3],6,[5,[1,0]]], 则最终应该输出:1, 4, 3, 6, 5, 1, 0 。 另外,实现一个 allObjects 方法,可以一次性取出所有元素。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// NSArray+FlatEnumerator.h | |
// Flay Array | |
// | |
// Created by yiplee on 2016/12/13. | |
// | |
#import <Foundation/Foundation.h> | |
@class NSArrayFlatEnumerator; | |
@interface NSArray (FlatEnumerator) | |
- (NSEnumerator *) flatEnumerator; | |
- (NSEnumerator *) reverseFlatEnumerator; | |
- (NSArray *) allObjects; | |
- (id) next; | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// NSArray+FlatEnumerator.m | |
// Flay Array | |
// | |
// Created by yiplee on 2016/12/13. | |
// | |
#import "NSArray+FlatEnumerator.h" | |
#import "NSArrayFlatEnumerator.h" | |
#import <objc/objc-runtime.h> | |
@implementation NSArray (FlatEnumerator) | |
- (NSEnumerator *) flatEnumerator | |
{ | |
return [NSArrayFlatEnumerator flatEnumeratorWithArray:self]; | |
} | |
- (NSEnumerator *) reverseFlatEnumerator | |
{ | |
return [NSArrayFlatEnumerator reverseFlatEnumeratorWithArray:self]; | |
} | |
- (NSArray *) allObjects | |
{ | |
return [[self flatEnumerator] allObjects]; | |
} | |
- (NSEnumerator *) _private_enumerator | |
{ | |
SEL key = _cmd; | |
NSArrayFlatEnumerator *enumator = objc_getAssociatedObject(self, key); | |
if (!enumator) { | |
enumator = (NSArrayFlatEnumerator*)[self flatEnumerator]; | |
objc_setAssociatedObject(self, key, enumator, OBJC_ASSOCIATION_RETAIN); | |
} | |
return enumator; | |
} | |
- (id) next | |
{ | |
return [[self _private_enumerator] nextObject]; | |
} | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// NSArrayFlatEnumerator.h | |
// Flay Array | |
// | |
// Created by yiplee on 2016/12/13. | |
// | |
#import <Foundation/Foundation.h> | |
@interface NSArrayFlatEnumerator : NSEnumerator | |
+ (instancetype) flatEnumeratorWithArray:(NSArray *)array; | |
+ (instancetype) reverseFlatEnumeratorWithArray:(NSArray *)array; | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// NSArrayFlatEnumerator.m | |
// Flay Array | |
// | |
// Created by yiplee on 2016/12/13. | |
// | |
#import "NSArrayFlatEnumerator.h" | |
#import <stack> | |
struct FlatArrayPoint { | |
__unsafe_unretained NSArray *currentArray; | |
NSInteger currentIndex; | |
}; | |
typedef struct FlatArrayPoint FlatArrayPoint; | |
#define FlatArrayInitialIndex NSIntegerMin | |
static FlatArrayPoint* flatArrayPointWithArray(NSArray *array) { | |
FlatArrayPoint *point = (FlatArrayPoint*)calloc(1, sizeof(FlatArrayPoint)); | |
point->currentArray = array; | |
point->currentIndex = FlatArrayInitialIndex; | |
return point; | |
} | |
static void freeFlatArrayPoint(FlatArrayPoint *point) { | |
point->currentArray = nil; | |
free(point); | |
} | |
@implementation NSArrayFlatEnumerator | |
{ | |
NSArray *_array; | |
std::stack<FlatArrayPoint *> _stack; | |
BOOL _reverse; | |
} | |
- (void) dealloc | |
{ | |
while (!_stack.empty()) { | |
FlatArrayPoint *point = _stack.top(); | |
_stack.pop(); | |
freeFlatArrayPoint(point); | |
} | |
} | |
- (instancetype) initWithArray:(NSArray *)array reverse:(BOOL)reverse; | |
{ | |
NSParameterAssert(array); | |
self = [self init]; | |
if (self) { | |
_array = [NSArray arrayWithArray:array]; | |
_reverse = reverse; | |
FlatArrayPoint *point = flatArrayPointWithArray(_array); | |
_stack.push(point); | |
} | |
return self; | |
} | |
+ (instancetype) flatEnumeratorWithArray:(NSArray *)array | |
{ | |
return [[self alloc] initWithArray:array reverse:NO]; | |
} | |
+ (instancetype) reverseFlatEnumeratorWithArray:(NSArray *)array | |
{ | |
return [[self alloc] initWithArray:array reverse:YES]; | |
} | |
- (id) nextObject | |
{ | |
if (_stack.empty()) return nil; | |
FlatArrayPoint *topPoint = _stack.top(); | |
BOOL isArrayLooped = NO; | |
if (!topPoint->currentArray || topPoint->currentArray.count == 0) { | |
isArrayLooped = YES; | |
goto loop; | |
} | |
if (FlatArrayInitialIndex == topPoint->currentIndex) { | |
topPoint->currentIndex = _reverse ? (topPoint->currentArray.count - 1) : 0; | |
} else { | |
topPoint->currentIndex += _reverse ? -1 : 1; | |
} | |
if (topPoint->currentIndex < 0 || topPoint->currentIndex >= topPoint->currentArray.count) { | |
isArrayLooped = YES; | |
goto loop; | |
} | |
loop: | |
if (isArrayLooped) { | |
_stack.pop(); | |
freeFlatArrayPoint(topPoint); | |
return [self nextObject]; | |
} | |
id item = topPoint->currentArray[topPoint->currentIndex]; | |
if ([item isKindOfClass:[NSArray class]]) { | |
FlatArrayPoint *point = flatArrayPointWithArray(item); | |
_stack.push(point); | |
return [self nextObject]; | |
} else { | |
return item; | |
} | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@tangqiaoboy 如果要整个 copy 一遍的话效率太低了,迭代过程中嵌套数组有变化无法避免。