《Objective-C 编程》24.Collection 集合类

Collection 类的实例用于保存指向其他对象的指针。Collection 类包括:


NSArray 、NSMutableArray

NSSet 、NSMutableSet

  • NSSet 对象所包含的“内容”是无序的。而且在一个 NSSet 对象中,某个特定的对象只能出现一次(唯一性)。
  • NSSet 对象的最大用处是检查某个对象是否存在NSSet 完成此类任务的速度比数组快得多。

NSSet 与 NSArray 的区别:

  • NSSet 和数组一样,是个数据容器。
  • 数组是有序的,NSSet是无序的。
  • 数组可以容纳重复对象,NSSet 不能。
  • 数组是有下标的,NSSet 没有下标。

NSSet 的创建

// alloc 创建
NSSet *set1 = [[NSSet alloc] initWithObjects:@“张三”,@“李四”, nil];

// 类方法创建
NSSet *set2 = [NSSet setWithObjects:s@“张三”,@“李四”,nil];

其他集合常用创建方法

// 创建一个新的集合1,集合2有两个对象(a和b)
NSSet *set1 = [NSSet setWithObjects:@"a", nil];
NSSet *set2 = [set1 setByAddingObject:@"b"];
    
// 通过已有集合7和集合8,创建一个新的集合9
NSSet *set7 = [NSSet setWithObjects:@"a", nil];
NSSet *set8 = [NSSet setWithObjects:@"z", nil];
NSSet *set9 = [set7 setByAddingObjectsFromSet:set8];
    
// 通过已有的集合10和数组对象,创建一个新的集合11
NSArray *array = [NSArray arrayWithObjects:@"a", @"b", @"c", nil]; 
NSSet *set10 = [NSSet setWithObjects:@"z", nil];
NSSet *set11 = [set10 setByAddingObjectsFromArray:array]; 

NSSet 与 NSArray 相互转换

// NSSet -> NSArray
NSArray *array = [set1 allObjects];

// NSArray --> NSSet
// 如果同一个对象在数组中出现多次,那么它只会添加一次到给定的集合。 每个对象在被添加到集合中时只会收到一次保留消息。
NSSet *set3 = [NSSet setWithArray:array];

返回集合元素的个数

NSUInteger count = [set1 count];

从容器中随机取出一个元素

NSString *s = [set1 anyObject];

判断对象是否在 NSSet 中已经存在

- (BOOL)containsObject:(ObjectType)anObject;

示例:

BOOL isContain = [set1 containsObject:@"李四"]; 
  • NSSet 对象中的对象是无序的,所以不能通过索引来访问,只能向 NSSet 对象查询某一个对象是否存在。
  • NSSet 收到 - (BOOL)containsObject:(ObjectType)anObject; 消息时,会在其包含的对象中查找和 anObject 相等的对象 (内容相同,地址可能不同,也就是说可能 【指针指向的内容是相等的】,但是他们两个【未必是同一块地址】,返回 YES)。
  • 因此,相同的变量(指针指向同一块内存地址)一定是相等的,而相等的变量不一定是相同的。

NSMutableSet

NSMutableSet 是可变集合,它继承自 NSSet

常用方法

// 创建一个空的集合
NSMutableSet *set1 = [NSMutableSet set];
NSMutableSet *set2 = [NSMutableSet setWithObjects:@"1", @"2", nil]; 
    
// 集合2“减去”集合3中的元素
[set2 minusSet:set3];
    
// 集合2与集合3中元素的交集
[set2 intersectSet:set3];
    
// 集合2与集合3中的元素的并集;
[set2 unionSet:set3];
    
// 将空集合1设置为集合3中的内容
[set1 setSet:set3];
    
// 根据数组的内容删除集合中的对象
[set2 addObjectsFromArray:array];
[set2 removeObject:@"1"];
[set2 removeAllObjects];    

NSDictionary

  • 字典是由 键—值对组成的数据容器, 通过 key (键,通常是字符串),查找对应 value (值,可以是任意类型的对象)。
  • 字典中的 键—值对是无序的。
  • 字典对象中的都是独一无二的,如果想要在现存的键后再添加第二个对象,第一个键—值对就会被替换掉。
  • 字典中的key可以是任意类型,一般使用字符串作为一个元素的 key。
  • NSDictionary 是不可变字典。

字典的创建

NSArray *array1 = @[@"zhang3",@"zhangfei"];
NSArray *array2 = @[@"li4",@"liming"];
 
/*
 字典的结构
 第一个元素:key:@"zhang"     value:array1
 第二个元素:key:@"li"        value:array2
 ...
 */

// 1.alloc方法创建
NSDictionary *dic1 = [[NSDictionary alloc] initWithObjectsAndKeys:
                      array1,@"zhang",
                      array2,@"li", nil];
                      
// xcode4.4以后对字典的创建和访问,语法上做了优化。
NSDictionary *dic11 = @{
                        @"zhang":array1,
                        @"li":array2
                       };
                       
// 2.类方法创建字典 
NSDictionary *dic2 = [NSDictionary dictionaryWithObjectsAndKeys: 
                                      array1,@"zhang",
                                      array2,@"li", nil];

返回字典元素个数

NSUInteger count = [dic1 count];

通过 key 获取对应的 value

NSArray *array3 = [dic1 objectForKey:@"zhang"];

// 简便写法
NSArray *array3 = dic1[@"zhang"];

取得所有的 keys

NSArray *allkeys = [dic1 allKeys];

取得所有的 Values

NSArray *allvalue = [dic1 allValues];  //同下get方法
NSArray *allvalue2 = dic1.allValues;

遍历字典

// 1.普通遍历
NSArray *keys = [dic1 allKeys];   //NSDictionary -> NSArray
for (int i =0;i <keys.count;i++) {
  NSString *key = keys[i]; //通过下标获取对象key

  NSArray *names =[dic1 objectForKey:key]; //通过key获取对应的value
  NSLog(@"key=%@,value=%@",key,names);
}

// 2.快速遍历
for (NSString *key in dic1) {
  NSArray *names = [dic1 objectForKey:key];
  NSLog(@"key=%@,value=%@",key,names);
}

删除服务器返回的 value 为 NULL 的情况

#import <Foundation/Foundation.h>

/**
 范畴
 */
@interface NSDictionary (MyCustomize)

/**
 填充value为空造成的crash

 @return 修改后的NSDictionary
 */
- (NSDictionary *)deleteAllNULLValue;

@end

#import "NSDictionary+MyCustomize.h"

/**
 自定义范畴类
 */
@implementation NSDictionary (MyCustomize)

- (NSDictionary *)deleteAllNULLValue {
    NSMutableDictionary *mutableDic = [[NSMutableDictionary alloc] init];
    for (NSString *keyStr in self.allKeys) {
        if ([[self objectForKey:keyStr] isEqual:[NSNull null]]) {
            [mutableDic setObject:@"null" forKey:keyStr];
            HQLog(@"changed!");
        }
        else{
            [mutableDic setObject:[self objectForKey:keyStr] forKey:keyStr];
            HQLog(@"no null");
        }
    }
    return mutableDic;
}

@end

NSMutableDictionary

NSMutableDictionary 是可变字典,字典中的存储是可以修改的。NSMutableDictionary 继承于 NSDictionary

创建可变字典

// 1.alloc 方法创建
NSArray *array = [NSArray arrayWithObjects:@"张三",@"李四",@"王五", nil];
NSMutableDictionary *mdic = [[NSMutableDictionary alloc] 
                               initWithObjectsAndKeys:array,@"names", nil];
    
NSMutableDictionary *mdic1 = [[NSMutableDictionary alloc] init];
[mdic1 setObject:array forKey:@"names"]; // 添加元素
    
NSMutableDictionary *mdic2 = [[NSMutableDictionary alloc] initWithCapacity:3];

添加元素

// 如果key是重复的,会将之前的value覆盖掉
[mdic setObject:@"value" forKey:@"zhang"];
    
// 将另外一个字典所有的元素添加到mdic中
[mdic addEntriesFromDictionary:<#(nonnull NSDictionary *)#>];

删除元素

// 1>根据Key删除元素
[mdic removeObjectForKey:@"names"];
    
// 2>根据多个key删除多个元素
[mdic removeObjectForKey:@[@"zhang",@"li"]];
    
// 3>删除所有元素
[mdic removeAllObjects];

数组排序

第17章——NSMutableArray

过滤

  1. 匹配字符串:正则表达式
// 正则表达式:验证码
- (BOOL) validateYzm:(NSString *)yzm {
    NSString *regex = @"^\\d{4}$";
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex];
    return [predicate evaluateWithObject:yzm];
}
  1. 过滤 collection
  • NSMutableArray 有一个名为 - filterUsingPredicate: 的方法,通过该方法可以很方便地剔除所有不能“满足”传入的 NSPredicate 对象的对象。
  • NSArray 有一个名为 filteredArrayUsingPredicate: 的方法,可以创建一个新的数组,包含所有能够满足传入的 NSPredicate 对象的对象。
// 要收回拥有物品总价值高于75美元的员工的物品
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"holder.valueOfAssets > 70"];

NSArray *toBeReclaimed = [allAssets filteredArrayUsingPredicate:predicate];

NSLog(@"toBeReclaimed:%@",toBeReclaimed);

NSSet 也有一个方法可以来做过滤,代码如下:

- (NSSet<ObjectType> *)filteredSetUsingPredicate:(NSPredicate *)predicate;

NSMutableSet 也有一个这样的方法,如下:

- (void)filterUsingPredicate:(NSPredicate *)predicate;

NSNull

collection 对象不能保存 nil。如果要将“空洞”加入集合对象中,可以使用 NSNull 类。NSNull 类只有一个实例,代表“空”。

示例代码如下:

NSMutableArray *hotel = [[NSMutableArray alloc] init];

// 底楼大厅
[hotel addObject:@"lobby"];

// 二楼泳池
[hotel addObject:@"pool"];

// 三楼未建,为空!!!
[hotel addObject:[NSNull null]];

// 四楼卧室
[hotel addObject:@"bedrooms"];

NSIndexSet

这个类用于存储有序的索引到某种数据结构,比如数组。例如,使用这个类可以生成一份数组对象的索引号清单,这些对象满足指定的查询条件。

- (NSUInteger)indexOfObjectPassingTest:

示例代码:

NSArray *array = @[@1, @2, @3, @4, @5];

// 遍历数组,取出满足条件的数组索引
NSUInteger result = [array indexOfObjectPassingTest:^BOOL(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
    if ([(NSNumber *)obj intValue] % 2 == 0) {
        return YES;
    }else {
        return NO;
    }
}];

// 如果找到一个匹配,则查看并打印此项
if (result != NSNotFound) {
    NSLog(@"%@",array[result]); 
}

// >输出:2

结论:只可以返回一个索引。

- (NSIndexSet *)indexesOfObjectsPassingTest:

示例代码:

NSArray *array = @[@1, @2, @3, @4, @5];

// 遍历数组,取出满足条件数组的所有索引
NSIndexSet *result = [array indexesOfObjectsPassingTest:^BOOL(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
    if ([(NSNumber *)obj intValue] % 2 == 0) {
        return YES;
    }else {
        return NO;
    }
}];

// 遍历 NSIndexSet
[result enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL * _Nonnull stop) {
    NSLog(@"%@",array[idx]);
}];

// Output:
// 2017-11-17 10:20:13.694049+0800 Test[39023:9364337] 2
// 2017-11-17 10:20:13.694204+0800 Test[39023:9364337] 4

NSIndexSet 常用方法

// 创建一个空的索引集合
+ (instancetype)indexSet;
// 给定索引创建索引集合
+ (instancetype)indexSetWithIndex:(NSUInteger)value;
// 给定索引范围创建索引集合
+ (instancetype)indexSetWithIndexesInRange:(NSRange)range;

- (instancetype)initWithIndexesInRange:(NSRange)range NS_DESIGNATED_INITIALIZER;
// 根据另一个索引集合创建索引集合
- (instancetype)initWithIndexSet:(NSIndexSet *)indexSet NS_DESIGNATED_INITIALIZER;

// 给定索引值初始化索引集合
- (instancetype)initWithIndex:(NSUInteger)value;

// 判断两个索引集合是否相等
- (BOOL)isEqualToIndexSet:(NSIndexSet *)indexSet;

// 是否包含指定的索引
- (BOOL)containsIndex:(NSUInteger)value;
// 是否包含索引范围
- (BOOL)containsIndexesInRange:(NSRange)range;

// 遍历索引集合方法
- (void)enumerateIndexesUsingBlock:(void (NS_NOESCAPE ^)(NSUInteger idx, BOOL *stop))block API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0));
- (void)enumerateIndexesWithOptions:(NSEnumerationOptions)opts usingBlock:(void (NS_NOESCAPE ^)(NSUInteger idx, BOOL *stop))block API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0));
- (void)enumerateIndexesInRange:(NSRange)range options:(NSEnumerationOptions)opts usingBlock:(void (NS_NOESCAPE ^)(NSUInteger idx, BOOL *stop))block API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0));

// ...
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容