数组与字典

参考:https://github.com/ming1016/study/wiki/iOS基础集合类

NSArray/NSMutableArray

基本使用

定义、初始化一个 NSArray,可以用以下的方式:

1
2
3
4
5
6
// NSArray: @[]
NSArray *instructors = @[ @"Joe", @"Tim", @"Jim", @"Tom", @"Mark" ];

// NSArray: arrayWithObjects/initWithObjects
NSArray *instructors = [NSArray arrayWithObjects:@"Joe", @"Tim", @"Jim", @"Tom", @"Mark", nil];
NSArray *instructors = [[NSArray alloc] initWithObjects:@"Joe", @"Tim", @"Jim", @"Tom", @"Mark", nil];

定义、初始化一个 NSMutableArray,可以用以下的方式:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// NSMutableArray: copy from NSArray
NSArray *instructors = @[ @"Joe", @"Tim", @"Jim", @"Tom", @"Mark" ];
NSMutableArray *mInstructors = [instructors mutableCopy];

// NSMutableArray: array with array
NSMutableArray *mInstructors = [NSMutableArray arrayWithArray:@[ @"Joe", @"Tim", @"Jim", @"Tom", @"Mark" ] ];

// NSMutableArray: 下面三种初始化空Array的方式是等价的,建议的方法是第一种
NSMutableArray *mEmpty = [[NSMutableArray alloc] init];
NSMutableArray *mEmpty = [NSMutableArray new];
NSMutableArray *mEmpty = [NSMutableArray array];

另外还有常用的函数 removeObject: / removeObject:atIndex: / insertObject: / insertObject:atIndex: / replaceObjectAtIndex:withObject: 等,不举例了。

排序

存储内容是字符串,可以用 @selector(localizedCaseInsensitiveCompare:) 排序:

1
2
NSArray *array = @[@"John Appleseed", @"Tim Cook", @"Hair Force One", @"Michael Jurewitz"];
NSArray *sortedArray = [array sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];

若存储内容为数字,可以用 @selector(compare:) 排序:

1
2
NSArray *numbers = @[@9, @5, @11, @3, @1];
NSArray *sortedNumbers = [numbers sortedArrayUsingSelector:@selector(compare:)];

除了 sortedArrayUsingSelector: 函数之外,另外还有其他排序函数:

1
2
3
4
5
6
7
8
// 函数指针 sortedArrayHint 的排序方式
- (NSData *)sortedArrayHint;
- (NSArray *)sortedArrayUsingFunction:(NSInteger (*)(id, id, void *))comparator context:(void *)context;
- (NSArray *)sortedArrayUsingFunction:(NSInteger (*)(id, id, void *))comparator context:(void *)context hint:(NSData *)hint;

// 基于block的排序方法
- (NSArray *)sortedArrayUsingComparator:(NSComparator)cmptr;
- (NSArray *)sortedArrayWithOptions:(NSSortOptions)opts usingComparator:(NSComparator)cmptr;

三种方式的性能比较:selector 性能 > block 性能 > function 性能

枚举遍历

使用 indexesOfObjectsWithOptions:passingTest 过滤:

1
2
3
4
NSIndexSet *indexes = [randomArray indexesOfObjectsWithOptions:NSEnumerationConcurrent passingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
     return testObj(obj);
}];
NSArray *filteredArray = [randomArray objectsAtIndexes:indexes];

传统的枚举遍历方式(本质是使用 NSFastEnumeration):

1
2
3
4
5
6
NSMutableArray *mutableArray = [NSMutableArray array];
for (id obj in randomArray) {
     if (testObj(obj)) {
          [mutableArray addObject:obj];
     }
}

BLOCK 的遍历方式:

1
2
3
4
5
6
NSMutableArray *mutableArray = [NSMutableArray array];
[randomArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
     if (testObj(obj)) {
          [mutableArray addObject:obj];
     }
}];

通过 [] 下标或 objectAtIndex: 方法遍历:

1
2
3
4
5
6
7
NSMutableArray *mutableArray = [NSMutableArray array];
for (NSUInteger idx = 0; idx < randomArray.count; idx++) {
     id obj = randomArray[idx];
     if (testObj(obj)) {
          [mutableArray addObject:obj];
     }
}

使用比较传统的学院派 NSEnumerator 迭代器遍历:

1
2
3
4
5
6
7
8
NSMutableArray *mutableArray = [NSMutableArray array];
NSEnumerator *enumerator = [randomArray objectEnumerator];
id obj = nil;
while ((obj = [enumerator nextObject]) != nil) {
     if (testObj(obj)) {
          [mutableArray addObject:obj];
     }
}

使用 predicate:

1
2
3
NSArray *filteredArray2 = [randomArray filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id obj, NSDictionary *bindings) {
     return testObj(obj);
}]];

上面的七种方法性能由高到低递减:

  • indexesOfObjectsWithOptions:NSEnumerationConcurrent > NSFastEnumeration > enumerateObjectsUsingBlock: > objectAtIndex: > NSEnumerator > filteredArrayUsingPredicate:

NSDictionary / NSMutableDictionary