// Created by EasyIOS on 14-4-10. // Copyright (c) 2014年 zhuchao. All rights reserved. // #import "NSArray+EasyExtend.h" #import "pinyin.h" // ---------------------------------- // Source code // ---------------------------------- #pragma mark - @implementation NSArray(EasyExtend) @dynamic APPEND; @dynamic mutableArray; - (NSArrayAppendBlock)APPEND { NSArrayAppendBlock block = ^ NSMutableArray * ( id obj ) { NSMutableArray * array = [NSMutableArray arrayWithArray:self]; [array addObject:obj]; return array; }; return [block copy]; } - (NSArray *)head:(NSUInteger)count { if ( [self count] < count ) { return self; } else { NSMutableArray * tempFeeds = [NSMutableArray array]; for ( NSObject * elem in self ) { [tempFeeds addObject:elem]; if ( [tempFeeds count] >= count ) break; } return tempFeeds; } } - (NSArray *)tail:(NSUInteger)count { // if ( [self count] < count ) // { // return self; // } // else // { // NSMutableArray * tempFeeds = [NSMutableArray array]; // // for ( NSUInteger i = 0; i < count; i++ ) // { // [tempFeeds insertObject:[self objectAtIndex:[self count] - i] atIndex:0]; // } // // return tempFeeds; // } // thansk @lancy, changed: NSArray tail: count NSRange range = NSMakeRange( self.count - count, count ); return [self subarrayWithRange:range]; } -(id)objectAtIndexPath:(NSIndexPath *)indexPath{ return [[self safeObjectAtIndex:indexPath.section] safeObjectAtIndex:indexPath.row]; } - (id)safeObjectAtIndex:(NSInteger)index { if ( index < 0 ) return nil; if ( index >= self.count ) return nil; return [self objectAtIndex:index]; } - (NSArray *)safeSubarrayWithRange:(NSRange)range { if ( 0 == self.count ) return nil; if ( range.location >= self.count ) return nil; if ( range.location + range.length >= self.count ) return nil; return [self subarrayWithRange:NSMakeRange(range.location, range.length)]; } - (NSMutableArray *)mutableArray { return [NSMutableArray arrayWithArray:self]; } - (NSString *)join:(NSString *)delimiter { if ( 0 == self.count ) { return @""; } else if ( 1 == self.count ) { return [NSString stringWithFormat:@"%@",[self objectAtIndex:0]]; } else { NSMutableString * result = [NSMutableString string]; for ( NSUInteger i = 0; i < self.count; ++i ) { [result appendString:[NSString stringWithFormat:@"%@",[self objectAtIndex:i]]]; if ( i + 1 < self.count ) { [result appendString:delimiter]; } } return result; } } -(NSString *)stringByWords{ NSMutableString *str = [NSMutableString string]; for (NSString *w in self) { [str appendString:w]; } return (NSString *)str; } - (NSArray *)reversedArray { NSMutableArray *array = [NSMutableArray arrayWithCapacity:[self count]]; NSEnumerator *enumerator = [self reverseObjectEnumerator]; for (id element in enumerator) { [array addObject:element]; } return array; } - (NSDictionary *)sortedArrayUsingFirstLetter { NSMutableDictionary *mutDic = [NSMutableDictionary dictionary]; const char *letterPoint = NULL; NSString *firstLetter = nil; for (NSString *str in self) { //检查 str 是不是 NSString 类型 if (![str isKindOfClass:[NSString class]]) { assert(@"object in array is not NSString"); continue; } letterPoint = [str UTF8String]; //如果开头不是大小写字母则读取 首字符 if (!(*letterPoint > 'a' && *letterPoint < 'z') && !(*letterPoint > 'A' && *letterPoint < 'Z')) { //汉字或其它字符 char strChar= [HTFirstLetter pinyinFirstLetter:[str characterAtIndex:0]]; letterPoint = &strChar; } //首字母转成大写 firstLetter = [[NSString stringWithFormat:@"%c", *letterPoint] uppercaseString]; //首字母所对应的 姓名列表 NSMutableArray *mutArray = [mutDic objectForKey:firstLetter]; if (mutArray == nil) { mutArray = [NSMutableArray array]; [mutDic setObject:mutArray forKey:firstLetter]; } [mutArray addObject:str]; } //字典是无序的,数组是有序的, //将数组排序 for (NSString *key in [mutDic allKeys]) { NSArray *nameArray = [[mutDic objectForKey:key] sortedArrayUsingSelector:@selector(compare:)]; [mutDic setValue:nameArray forKey:key]; } return mutDic; } - (NSArray *)map:(id (^)(id obj))block { __block NSMutableArray *array = [NSMutableArray arrayWithCapacity:[self count]]; [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { [array addObject:block(obj)]; }]; return array; } - (NSArray *)mapWithIndex:(id (^)(id obj, NSUInteger idx))block { __block NSMutableArray *array = [NSMutableArray arrayWithCapacity:[self count]]; [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { [array addObject:block(obj, idx)]; }]; return array; } - (NSArray *)each:(void (^)(id obj))block { [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { block(obj); }]; return self; } - (NSArray *)eachWithIndex:(void (^)(id obj, NSUInteger idx))block { [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { block(obj, idx); }]; return self; } - (NSArray *)eachWithStop:(void (^)(id obj, BOOL *stop))block { [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { block(obj, stop); }]; return self; } - (NSArray *)eachWithIndexAndStop:(void (^)(id obj, NSUInteger idx, BOOL *stop))block { [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { block(obj, idx, stop); }]; return self; } - (NSArray *)filter:(BOOL(^)(id obj))block { __block NSMutableArray *array = [NSMutableArray arrayWithCapacity:[self count]]; [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { if (block(obj)) { [array addObject:obj]; } }]; return [NSArray arrayWithArray:array]; } - (id)find:(BOOL(^)(id obj))block { __block id ret = nil; [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { if (block(obj)) { *stop = YES; ret = obj; } }]; return ret; } @end #pragma mark - // No-ops for non-retaining objects. static const void * __TTRetainNoOp( CFAllocatorRef allocator, const void * value ) { return value; } static void __TTReleaseNoOp( CFAllocatorRef allocator, const void * value ) { } #pragma mark - @implementation NSMutableArray(BeeExtension) @dynamic APPEND; - (NSMutableArrayAppendBlock)APPEND { NSMutableArrayAppendBlock block = ^ NSMutableArray * ( id obj ) { [self addObject:obj]; return self; }; return [block copy]; } + (NSMutableArray *)nonRetainingArray // copy from Three20 { CFArrayCallBacks callbacks = kCFTypeArrayCallBacks; callbacks.retain = __TTRetainNoOp; callbacks.release = __TTReleaseNoOp; return (NSMutableArray *)CFBridgingRelease(CFArrayCreateMutable( nil, 0, &callbacks )); } - (void)addUniqueObject:(id)object compare:(NSMutableArrayCompareBlock)compare { BOOL found = NO; for ( id obj in self ) { if ( compare ) { NSComparisonResult result = compare( obj, object ); if ( NSOrderedSame == result ) { found = YES; break; } } else if ( [obj class] == [object class] && [obj respondsToSelector:@selector(compare:)] ) { NSComparisonResult result = [obj compare:object]; if ( NSOrderedSame == result ) { found = YES; break; } } } if ( NO == found ) { [self addObject:object]; } } - (void)addUniqueObjects:(const id [])objects count:(NSUInteger)count compare:(NSMutableArrayCompareBlock)compare { for ( int i = 0; i < count; ++i ) { BOOL found = NO; id object = objects[i]; for ( id obj in self ) { if ( compare ) { NSComparisonResult result = compare( obj, object ); if ( NSOrderedSame == result ) { found = YES; break; } } else if ( [obj class] == [object class] && [obj respondsToSelector:@selector(compare:)] ) { NSComparisonResult result = [obj compare:object]; if ( NSOrderedSame == result ) { found = YES; break; } } } if ( NO == found ) { [self addObject:object]; } } } - (void)addUniqueObjectsFromArray:(NSArray *)array compare:(NSMutableArrayCompareBlock)compare { for ( id object in array ) { BOOL found = NO; for ( id obj in self ) { if ( compare ) { NSComparisonResult result = compare( obj, object ); if ( NSOrderedSame == result ) { found = YES; break; } } else if ( [obj class] == [object class] && [obj respondsToSelector:@selector(compare:)] ) { NSComparisonResult result = [obj compare:object]; if ( NSOrderedSame == result ) { found = YES; break; } } } if ( NO == found ) { [self addObject:object]; } } } - (void)unique { [self unique:^NSComparisonResult(id left, id right) { return [left compare:right]; }]; } - (void)unique:(NSMutableArrayCompareBlock)compare { if ( self.count <= 1 ) { return; } // Optimize later ... NSMutableArray * dupArray = [NSMutableArray nonRetainingArray]; NSMutableArray * delArray = [NSMutableArray nonRetainingArray]; [dupArray addObjectsFromArray:self]; [dupArray sortUsingComparator:compare]; for ( NSUInteger i = 0; i < dupArray.count; ++i ) { id elem1 = [dupArray safeObjectAtIndex:i]; id elem2 = [dupArray safeObjectAtIndex:(i + 1)]; if ( elem1 && elem2 ) { if ( NSOrderedSame == compare(elem1, elem2) ) { [delArray addObject:elem1]; } } } for ( id delElem in delArray ) { [self removeObject:delElem]; } } - (void)sort { [self sort:^NSComparisonResult(id left, id right) { return [left compare:right]; }]; } - (void)sort:(NSMutableArrayCompareBlock)compare { [self sortUsingComparator:^NSComparisonResult(id obj1, id obj2) { return compare( obj1, obj2 ); }]; } - (NSMutableArray *)pushHead:(NSObject *)obj { if ( obj ) { [self insertObject:obj atIndex:0]; } return self; } - (NSMutableArray *)pushHeadN:(NSArray *)all { if ( [all count] ) { for ( NSUInteger i = [all count]; i > 0; --i ) { [self insertObject:[all objectAtIndex:i - 1] atIndex:0]; } } return self; } - (NSMutableArray *)popTail { if ( [self count] > 0 ) { [self removeObjectAtIndex:[self count] - 1]; } return self; } - (NSMutableArray *)popTailN:(NSUInteger)n { if ( [self count] > 0 ) { if ( n >= [self count] ) { [self removeAllObjects]; } else { NSRange range; range.location = n; range.length = [self count] - n; [self removeObjectsInRange:range]; } } return self; } - (NSMutableArray *)pushTail:(NSObject *)obj { if ( obj ) { [self addObject:obj]; } return self; } - (NSMutableArray *)pushTailN:(NSArray *)all { if ( [all count] ) { [self addObjectsFromArray:all]; } return self; } - (NSMutableArray *)popHead { if ( [self count] ) { [self removeLastObject]; } return self; } - (NSMutableArray *)popHeadN:(NSUInteger)n { if ( [self count] > 0 ) { if ( n >= [self count] ) { [self removeAllObjects]; } else { NSRange range; range.location = 0; range.length = n; [self removeObjectsInRange:range]; } } return self; } - (NSMutableArray *)keepHead:(NSUInteger)n { if ( [self count] > n ) { NSRange range; range.location = n; range.length = [self count] - n; [self removeObjectsInRange:range]; } return self; } - (NSMutableArray *)keepTail:(NSUInteger)n { if ( [self count] > n ) { NSRange range; range.location = 0; range.length = [self count] - n; [self removeObjectsInRange:range]; } return self; } - (void)insertObjectNoRetain:(id)object atIndex:(NSUInteger)index { [self insertObject:object atIndex:index]; } - (void)addObjectNoRetain:(NSObject *)object { [self addObject:object]; } - (void)removeObjectNoRelease:(NSObject *)object { [self removeObject:object]; } - (void)removeAllObjectsNoRelease { [self removeAllObjects]; } - (void)removeObject:(NSObject *)obj usingComparator:(NSMutableArrayCompareBlock)cmptr { if ( nil == cmptr || nil == obj ) return; NSMutableArray * objectsWillRemove = [NSMutableArray nonRetainingArray]; for ( id obj2 in self ) { NSComparisonResult result = cmptr( obj, obj2 ); if ( NSOrderedSame == result ) { [objectsWillRemove addObject:obj2]; } } [self removeObjectsInArray:objectsWillRemove]; } - (void)reverse { if ([self count] <= 1) return; NSUInteger i = 0; NSUInteger j = [self count] - 1; while (i < j) { [self exchangeObjectAtIndex:i withObjectAtIndex:j]; i++; j--; } } @end