集合是一组单值对象,它可以是可变的,也可以是不可变的,可变集合可以删除、添加、搜索集合中得成员,比较两个集合,计算两个集合的交集和并集。
现在因为要在程序执行的时候多次显示集合的内容,所以可以创建一个名为print的新方法,通过创建一个名为Printing新分类,将print方法加入到NSSet类中,因为NSMutableSet类是NSSet类的子类,所以可变集合也可以使用这个方法。
现有如下代码:
#import <Foundation/Foundation.h>
//创建一个整数对象
#define INTOBJ(v) [NSNumber numberWithInteger: v]
@interface NSSet (Printing)
-(void) print;
@end
@implementation NSSet (Printing)
-(void) print
{
printf("{");
for(NSNumber *elementin self)
printf(" %li",(long) [elementintegerValue]);
printf("}\n");
}
@end
int main ()
{
@autoreleasepool {
NSMutableSet *set1 = [NSMutableSetsetWithObjects:INTOBJ(1),INTOBJ(3),INTOBJ(5),INTOBJ(10),nil];
NSSet *set2 = [NSSetsetWithObjects:INTOBJ(-5),INTOBJ(100),INTOBJ(3),INTOBJ(5),nil];
NSSet *set3 = [NSSetsetWithObjects:INTOBJ(12),INTOBJ(200),INTOBJ(3),nil];
NSLog(@"set1:");
[set1 print];
NSLog(@"set2:");
[set2 print];
//相等测试
if ([set2 isEqualToSet: set1] ==YES)
NSLog(@"set1 eqauls set2");
else
NSLog(@"set1 is not eqaul to set2");
//成员测试
if ([set1 containsObject:INTOBJ(10)] ==YES) {
NSLog(@"set1 contain 10");
}
else
NSLog(@"set1 does not contain 10");
if ([set2 containsObject:INTOBJ(10)] ==YES)
NSLog(@"set2 contain 10");
else
NSLog(@"set2 does not contain 10");
//在可变集合Set1中添加和移除对象
[set1 addObject: INTOBJ(4)];
[set1 removeObject:INTOBJ(10)];
NSLog(@"set1 after adding 4 and removeing 10");
[set1 print];
//获得两个集合的交集
[set1 intersectSet: set2];
NSLog(@"set1 intersect set2: ");
[set1 print];
//两个集合的并集
[set1 unionSet:set3];
NSLog(@"set1 union set3:");
[set1 print];
}
return 0;
}
运行结果:2014-08-29 20:39:45.655 testOC[587:303] set1:
{ 3 10 5 1}
2014-08-29 20:39:45.656 testOC[587:303] set2:
{ 3 100 -5 5}
2014-08-29 20:39:45.657 testOC[587:303] set1 is not eqaul to set2
2014-08-29 20:39:45.657 testOC[587:303] set1 contain 10
2014-08-29 20:39:45.658 testOC[587:303] set2 does not contain 10
2014-08-29 20:39:45.658 testOC[587:303] set1 after adding 4 and removeing 10
{ 3 5 1 4}
2014-08-29 20:39:45.658 testOC[587:303] set1 intersect set2:
{ 3 5}
2014-08-29 20:39:45.659 testOC[587:303] set1 union set3:
{ 3 5 12 200}
Program ended with exit code: 0
本程序定义了一个名为INTOBJ的宏,根据整数数值创建整型对象,这会使你的程序更加简洁,并节省一些输入。这里还有一个提示,提醒我们如何通过创建分类将方法添加到类中。使用isEqualToSet: 方法测试两个集合是否相等。
使用containsObject:方法查询对象是否在集合中,方法返回Boolean值验证对象是否在集合中。
使用addObject:和removeObject:方法来添加和删除集合中的对象。
使用intersectSet:和unionSet:方法计算两个集合的交集和并集。并且这两种情况中,运算符的结果取代了消息的接收者。
Foundation框架中还提到一个名字为NSCountedSet的类。这种集合同一对象可以多次出现,然而并非在集合中存放多次这个对象,二是维护一个次数计数。当第一次将一个对象添加到这个对象时,对象的count值为1,然后每次将这个对象添加到集合中,count值都会加一,每次从集合中删除这个对象,count值都会减一。当对象的count值为0时,实际上这个对象已经被删除。使用countForObject:可以在集合中检索某个对象的count值。
常用的NSSet方法
常用的NSMutablieSet方法
obj,obj1,obj2是任意对象,nsset是NSMutableIeset类或NSSet类的对象,size是一个NSUInteger整数。
NSIndexSet类
这个用于存储有序的索引到某种数据结构,比如:数组。例如:使用这个类可以生成一份数组对象的索引号清单,这些对象满足指定的查询条件。需要注意的是,并没有可变的NSIndexSet类。
NSArray的方法indexOfObjectPassingTest:以一个区块作为参数。针对数组中的每一个元素对区块执行操作。传递数组的元素,索引号,和一个指向BOOL变量的指针给区块。使用区块中的代码测试元素是否满足条件,如果数组中得元素满足条件,则返回yes,不满足返回no,即使返回yes,仍然会继续执行,直到所有元素均被处理过。可以设置BOOL指针引用的值为YES终止处理。
如果ndexOfObjectPassingTest:查找到一个匹配的元素(区块至少返回一次YES),则返回从集合匹配的最小索引值,否则返回NSNotFound。
下面是对AddressBook类的lookup:方法进行修改:
-(AddressCard *) lookup: (NSString *) theName
{
NSUInteger result = [book ndexOfObjectPassingTest:
^ (id obj,NSUInteger , BOOL *stop){
if( [[obj name] caseInsensitiveCompare: theName] ==NSOrderedSame){
*stop = YES;//找到一个匹配,一个就足够了
return YES;
}
else
return NO;//继续查找
}];
//如果找到一个匹配的,则查看它
if (result != NSNotFound)//只有一个元素
return [book objectAtIndex: result];
else
return nil;
}
如果从数组中查找到匹配的所有对象,则需要将他们存储在区块的数组中,并且不需要设置stop指针为YES,以这种方试使用ndexOfObjectPassingTest:方法,测试数组中的所有的元素,代码如下:
-(NSMutableArray *) lookupAll: (NSString *) theName
{
NSMutableArray *matches = [NSMutableArray array];
NSUInteger result = [book indexOfObjectPassingTest:
^ (id obj,NSUInteger , BOOL *stop){
if( [[obj name] caseInsensitiveCompare: theName] ==NSOrderedSame){
[matches addObject: obj];
return YES;
}
else
return NO;
}];
//如果找到匹配。则查看它
if ([matches count])
return matches;
else
return nil;
}
如果需要从数组中查找多个匹配的对象,也可以使用indexOfObjectPassingTest: i方法,lookupAll:方法返回NSIndexSet,包含数组中满足条件的所有元素的索引。
-(NSIndexSet *) lookupAll: (NSString *) theName
{
NSIndexSet result = [book indexOfObjectPassingTest:
^ (id obj,NSUInteger , BOOL *stop){
if( [[obj name] caseInsensitiveCompare: theName] ==NSOrderedSame){
return YES;
}
else
return NO;
}];
return result;
}
常用的NSIndexSet的一些方法