Collections Programming Topics---集合的编程问题

来源:互联网 发布:阿里云服务器导入sql 编辑:程序博客网 时间:2024/05/16 15:08
一、数组:有序集合
1,数组基础:
NSArray是不可变的个数组,你不能添加、移除或替换对象,你可以修改其元素本身的值。

NSMutableArray。
创建方法 initWithArray:或arrayWithArray:
当你向一个可变数组中添加对象时,对象不是被拷贝进去的,除非你传递YES参数给 initWithArray:copyItems:方法。添加到数组中的对象为强引用。
基本访问方法: count 和 objectAtIndex: 

2,可变数组: addObject:   insertObject:atIndex:    removeLastObject:  removeObjectAtIndex:   replaceObjectAtIndex:withObject:

3,使用数组:objectEnumerator 和 reverseObjectEnumerator 返回顺序枚举和反向枚举。
makeObjectsPerformSelector: 和 makeObjectsPerformSelector:withObject: 让你给数组中的所有元素发送消息。
在很多时候,应该使用快速枚举,因为更快和更灵活。

使用subarrayWithRange:获得数组的子集合  或 连接数组中的元素为一个字符串 componentsJoinedByString:
另外,你可以使用 isEqualToArray:和firstObjectCommonWithArray:方法来比较数组。
最后,你还可以通过数组的方法 arrayByAddingObject: 或 arrayByAddingObjectsFromArray: 来创建一个新的数组

有2个方法可以确定一个数组是否包含一个对象: indexOfObject:  和 indexOfObjectIdenticalTo
在一个范围内搜索: indexOfObject:inRange: 和 indexOfObjectIdenticalTo:inRange:
indexOfObject:方法测试数组中的每个元素的isEqual:消息
indexOfObjectIdenticalTo:方法测试指针比较。他们的区别如下所示:

4,排序数组:Cocoa提供了遍历方法来排序,例如sort descriptors,blocks 和 selectors
1)通过sort Descriptors排序:
NSSortDescriptor实例。如果你使用sortedArrayUsingDescriptors: 或 sortUsingDescriptors:.如下所示:

Listing 3  Creating and sorting an array of dictionaries
//First create the array of dictionaries
NSString *last = @"lastName";
NSString *first = @"firstName";
 
NSMutableArray *array = [NSMutableArray array];
NSArray *sortedArray;
 
NSDictionary *dict;
dict = [NSDictionary dictionaryWithObjectsAndKeys:
                     @"Jo", first, @"Smith", last, nil];
[array addObject:dict];
 
dict = [NSDictionary dictionaryWithObjectsAndKeys:
                     @"Joe", first, @"Smith", last, nil];
[array addObject:dict];
 
dict = [NSDictionary dictionaryWithObjectsAndKeys:
                     @"Joe", first, @"Smythe", last, nil];
[array addObject:dict];
 
dict = [NSDictionary dictionaryWithObjectsAndKeys:
                     @"Joanne", first, @"Smith", last, nil];
[array addObject:dict];
 
dict = [NSDictionary dictionaryWithObjectsAndKeys:
                     @"Robert", first, @"Jones", last, nil];
[array addObject:dict];
 
//Next we sort the contents of the array by last name then first name
 
// The results are likely to be shown to a user
// Note the use of the localizedCaseInsensitiveCompare: selector
NSSortDescriptor *lastDescriptor =
    [[NSSortDescriptor alloc] initWithKey:last
                               ascending:YES
                               selector:@selector(localizedCaseInsensitiveCompare:)];
NSSortDescriptor *firstDescriptor =
    [[NSSortDescriptor alloc] initWithKey:first
                               ascending:YES
                               selector:@selector(localizedCaseInsensitiveCompare:)];
 
NSArray *descriptors = [NSArray arrayWithObjects:lastDescriptor, firstDescriptor, nil];
sortedArray = [array sortedArrayUsingDescriptors:descriptors];

很容易更改排序规则,如下所示:
Listing 4  Sorting by first name, last name
NSSortDescriptor *lastDescriptor =
    [[NSSortDescriptor alloc] initWithKey:last
                               ascending:NO
                               selector:@selector(localizedCaseInsensitiveCompare:)];
NSSortDescriptor *firstDescriptor =
    [[NSSortDescriptor alloc] initWithKey:first
                               ascending:NO
                               selector:@selector(localizedCaseInsensitiveCompare:)];
NSArray *descriptors = [NSArray arrayWithObjects:firstDescriptor, lastDescriptor, nil];
sortedArray = [array sortedArrayUsingDescriptors:descriptors];

尤其是,根据用户的输入创建sort descriptors是很简单的。

相反地,下面例示了使用函数排序。这种方法不是很灵活。
Listing 5  Sorting with a function is less flexible
NSInteger lastNameFirstNameSort(id person1, id person2, void *reverse)
{
    NSString *name1 = [person1 valueForKey:last];
    NSString *name2 = [person2 valueForKey:last];
 
    NSComparisonResult comparison = [name1 localizedCaseInsensitiveCompare:name2];
    if (comparison == NSOrderedSame) {
 
        name1 = [person1 valueForKey:first];
        name2 = [person2 valueForKey:first];
        comparison = [name1 localizedCaseInsensitiveCompare:name2];
    }
 
    if (*(BOOL *)reverse == YES) {
        return 0 - comparison;
    }
    return comparison;
}
 
BOOL reverseSort = YES;
sortedArray = [array sortedArrayUsingFunction:lastNameFirstNameSort
        context:&reverseSort];
        
5,使用blocks排序:
NSArray的方法sortedArrayUsingComparator: 来创建排序后的数组
NSMutableArray的 sortUsingComparator: 方法来更改自身为排序后的数组

Listing 6  Blocks ease custom sorting of arrays
NSArray *sortedArray = [array sortedArrayUsingComparator: ^(id obj1, id obj2) {
 
    if ([obj1 integerValue] > [obj2 integerValue]) {
          return (NSComparisonResult)NSOrderedDescending;
     }
 
     if ([obj1 integerValue] < [obj2 integerValue]) {
          return (NSComparisonResult)NSOrderedAscending;
     }
     return (NSComparisonResult)NSOrderedSame;
}];

6,使用Functions和Selectors排序:
sortedArrayUsingSelector: , sortedArrayUsingFunction:context: 和 sortedArrayUsingFunction:context:hint: 
最复杂的函数是sortedArrayUsingFunction:context:hint: .当你有一个大的数组(N个入口)被排序过一次,然后只有轻微地更改(增加或删除P个入口,P 远小于N)时, Hinted sort是最有效率的排序。要得到一个合适的hint,你可以在原始的数组被排序过后,使用其实例方法sortedArrayHint,然后保留它直到你需要它的时候(在其被修改后,你想重新对其排序的时候)。

Listing 7  Sorting using selectors and functions
NSInteger alphabeticSort(id string1, id string2, void *reverse)
{
    if (*(BOOL *)reverse == YES) {
        return [string2 localizedCaseInsensitiveCompare:string1];
    }
    return [string1 localizedCaseInsensitiveCompare:string2];
}
 
NSMutableArray *anArray =
    [NSMutableArray arrayWithObjects:@"aa", @"ab", @"ac", @"ad", @"ae", @"af", @"ag",
        @"ah", @"ai", @"aj", @"ak", @"al", @"am", @"an", @"ao", @"ap", @"aq", @"ar", @"as", @"at",
        @"au", @"av", @"aw", @"ax", @"ay", @"az", @"ba", @"bb", @"bc", @"bd", @"bf", @"bg", @"bh",
        @"bi", @"bj", @"bk", @"bl", @"bm", @"bn", @"bo", @"bp", @"bq", @"br", @"bs", @"bt", @"bu",
        @"bv", @"bw", @"bx", @"by", @"bz", @"ca", @"cb", @"cc", @"cd", @"ce", @"cf", @"cg", @"ch",
        @"ci", @"cj", @"ck", @"cl", @"cm", @"cn", @"co", @"cp", @"cq", @"cr", @"cs", @"ct", @"cu",
        @"cv", @"cw", @"cx", @"cy", @"cz", nil];
// note: anArray is sorted
NSData *sortedArrayHint = [anArray sortedArrayHint];

 
[anArray insertObject:@"be" atIndex:5];
 
NSArray *sortedArray;
 
// sort using a selector
sortedArray =
        [anArray sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
 
// sort using a function
BOOL reverseSort = NO;
sortedArray =
        [anArray sortedArrayUsingFunction:alphabeticSort context:&reverseSort];
 
// sort with a hint
sortedArray =
        [anArray sortedArrayUsingFunction:alphabeticSort
                                  context:&reverseSort
                                     hint:sortedArrayHint];


7,过滤数组:
filteredArrayUsingPredicate:  和  filterUsingPredicate: 

8,数组指针:
NSPointerArray,在iOS中不可用。


二、字典:键-值的集合
键是唯一的(通过isEqual:决定键是否相同)。键可以是任何遵循NSCopying协议和实现了hash和isEqual:方法的对象。

1,字典基础:NSDictionary和NSMutableDictionary
initWithDictionary: 和 dictionaryWithDictionary:
加入到字典中的对象不是拷贝的,除非指定copyItems参数为YES。

2,使用可变字典:
setObject:forKey:
addEntriesFromDictionary:

3,排序字典:
keysSortedByValueUsingSelector:
keysSortedByValueUsingComparator: 使用block

4,使用自定义Keys:
Key必须遵循NSCopying协议和实现hash和isEqual:方法

5,使用Map Tables:
NSMapTable类 ,在iOS中不可用。


三、Sets:无序集合
1,Set基础:
NSSet、NSMutableSet
NSCountedSet是NSMutableSet的一个子类,可以多次添加相同的对象。换句话说,set中的对象不必是唯一的。它也被成为bag。NSCountedSet跟踪对象添加的次数,并且需要移除相同的次数来完全移除其中的对象。因此,只有一个对象在Counted Set中,即使对象被添加了很多次。countForObject:方法返回被添加的次数。
Set中的对象必须响应NSObject协议的hash和isEqual:方法。如果可变对象被排序,对象的hash方法不应该基于可变对象的内部状态,而且可变对象也不能被更改。例如,一个可变字典可以被放入到一个set中,但是在其在set期间,你不能更改它。
(也就是说set中的对象不能被更改?)
NSSet提供了很多初始化函数,如setWithObjects:和initWithArray:。对象不是拷贝的(除非指定copyItems)

2,可变Sets:
创建方法 setWithSet: 或 initWithSet:
添加方法:addObject:  、 addObjectsFromArray: 、 unionSet: 
移除方法:intersectSet: 移除所有不在另一个set中的对象
removeAllObjects:
removeObject:
minusSet: 移除所有在另一个set中的对象

NSCountedSet有一些不同:
unionSet: 添加另一个set中的所有对象,即使他们已经存在
intersectSet: 移除所有不在另一个set中的对象,不管在哪个set中,有相同对象的多个实例,结果set中包含两个集合中包含该实例较少的次数。
minusSet:  移除所有在另一个set中的对象.如果对象在counted Set中存在于多次,它只是被移除一次。

3,使用Sets:
allObjects: 
anyObject: 不是随机的
count
member: 返回isEqual:的对象
intersectsSet: 测试两个set共享至少一个对象
isEqualToSet: 测试两个set是否相等
isSubSetOfSet: 测试set中的所有元素是否包含于另一个set中。

objectEnumerator
makeObjectsPerformSelector: 、 makeObjectsPerformSelector:withObject: 

4,Hash Tables:
NSHashTable,在iOS中不可用。

四、Index Sets:Storing Indexes into an Array
1,Index Set基础:
NSIndexSet对象管理不可变的一组indexes
NSMutableIndexSet
创建方法:initWithIndexSet:

2,可变Index Sets:
addIndex: 、 addIndexesInRange: 、 removeIndex: 、 removeIndexesInRange:

3,遍历Index Sets:
Listing 2  Forward iteration through an index set
NSUInteger index=[anIndexSet firstIndex];
 
while(index != NSNotFound)
{
 
     NSLog(@" %@",[anArray objectAtIndex:index]);
     index=[anIndexSet indexGreaterThanIndex: index];
}

反向遍历:
 index=[anIndexSet indexLessThanIndex: index];
 
removeObjectsAtIndexes:移除
removeObjectAtIndex:

4,Index sets和Blocks:
通过blocks,使用array创建IndexSet:

Listing 4  Creating an index set from an array using a block
NSIndexSet *lessThan20=[someArray indexesOfObjectsPassingTest:^(id obj, NSUInteger index, BOOL *stop){
     if ([obj isLessThan:[NSNumber numberWithInt:20]]){
          return YES;
     }
     return NO;
}];

使用enumerateObjectsAtIndexes:options:usingBlock:方法来遍历数组
相对地,你可以使用enumerateIndexesUsingBlock:方法来遍历Index Set本身。

Listing 5  Enumerating an index set to access multiple arrays
[anIndexSet enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop){
     if([[firstArray objectAtIndex: idx] isEqual:[secondArray objectAtIndex: idx]]){
          NSLog(@"Objects at %i Equal",idx);
     }
}];

五、Index Paths:Storing a Path Through Nested Arrays
1,Index Path基础:
创建Index Path:

Listing 1  Creating an index path from an array
NSUInteger arrayLength = 5;
NSUInteger integerArray[] = {0,0,1,1,2};
NSIndexPath *aPath = [[NSIndexPath alloc] initWithIndexes:integerArray length:arrayLength];

除了可以通过数组创建NSIndexPath之外,你还可以自动通过更复杂的集合结构来创建Index Path。
参照NSTreeNode类的例子。

2,使用Index Paths:
indexAtPosition: 返回给定postion的index
section row

六、拷贝集合:
有2种拷贝对象:浅复制和深复制

1,浅复制:copyItems:NO 表示浅复制,指示retain一次

2,深复制:copyItems:YES。

七、枚举:
1,快速枚举: for in
2,使用Block-Based枚举:
1)数组的block枚举:
Listing 2  Block-based enumeration of an array
NSArray *anArray = [NSArray arrayWithObjects:@"A", @"B", @"D", @"M", nil];
NSString *string = @"c";
 
[anArray enumerateObjectsUsingBlock:^(id obj, NSUInteger index, BOOL *stop){
     if ([obj localizedCaseInsensitiveCompare:string] == NSOrderedSame) {
          NSLog(@"Object Found: %@ at index: %i",obj, index);
          *stop = YES;
     }
} ];

2)NSSet的block枚举:
Listing 3  Block-based enumeration of a set
NSSet *aSet = [NSSet setWithObjects: @"X", @"Y", @"Z", @"Pi", nil];
NSString *aString = @"z";
 
[aSet enumerateObjectsUsingBlock:^(id obj, BOOL *stop){
     if ([obj localizedCaseInsensitiveCompare:aString]==NSOrderedSame) {
          NSLog(@"Object Found: %@", obj);
          *stop = YES;
     }
} ];

3,使用Enumerator:
NSEnumerator是一个简单的抽象类。使用nextObject,直到返回nil。不能在遍历完集合后"reset"。要想重新枚举,你需要重新创建一个新的枚举。

集合对象的objectEnumerator和reverseObjectEnumerator。  字典对象的keyEnumerator和objectEnumerator

八、Pointer Function Options:
原创粉丝点击