Objective-c:集合类型遍历方法详解
来源:互联网 发布:金星网络商学院 编辑:程序博客网 时间:2024/06/06 03:02
前言
在编程中经常需要遍历集合类型的元素,当前有多种方法实现此功能,初学者大多习惯于用标准的C语言循环,当然也可以使用 NSEnumerator
以及快速遍历(for-in
),Objective-c 引入‘块’特性后,又多出来几种新的遍历方式,采用这几种新的遍历方式,可大幅度简化代码过程。
本文主要讲解常用的几种集合类型:NSArray
、NSSet
以及NSDictionary
的遍历方式。
for 循环遍历
- 遍历数组(NSArray)
// 初始化数组NSArray *numbers = @[@1, @2, @3, @4, @5];// 遍历数组元素for (int i = 0; i < numbers.count; i++) { id obj = numbers[i]; NSLog(@"%@", obj);}
- 遍历集(NSSet)
// 初始化集NSSet *sets = [NSSet setWithObjects:@1, @2, @3, @4, @5, nil];// 获取集元素NSArray *objects = [sets allObjects];// 遍历集元素for (int i = 0; i < objects.count; i++) { id obj = objects[i]; NSLog(@"%@", obj);}
- 遍历字典(NSDictionary)
// 初始化字典NSDictionary *infomation = @{@"account" : @"admin", @"password": @123456, @"members" : @YES, @"state" : @"activation"};// 获取字典键NSArray *keys = [dicts.allKeys mutableCopy];// 遍历字典键值对for (int i = 0; i < keys.count; i++) { id key = keys[i]; id obj = dicts[key]; NSLog(@"%@", obj);}
Tips
1、字典与set都是“无序”的,所以无法根据特定的整数下标来直接访问其中的值,于是,在遍历的时候需要获取字典的所有键或是set里的所有对象,此过程将会造成额外开销。
2、for循环也可以实现方向遍历,计数器的值从“元素个数减1”开始,每次迭代时递减,直到0为止。执行方向遍历时,使用for循环会比其他方式简单很多。
NSEnumerator 遍历
NSEnumerator提供的
nextObject
方法,返回枚举里的下个对象。每次调用该方法时,其内部数据结构都会更新,使得下次调用方法时能返回下个对象。等到枚举中的全部对象都已返回之后,再调用就将返回nil,这表示达到枚举末端了。遍历数组(NSArray)
// 初始化数组NSArray *numbers = @[@1, @2, @3, @4, @5];// 创建枚举器NSEnumerator *enumerator = [numbers objectEnumerator];// 创建迭代元素id obj = nil;// 遍历数组元素while ((obj = [enumerator nextObject]) != nil) { NSLog(@"%@", obj);}
- 遍历集(NSSet)
// 初始化集NSSet *sets = [NSSet setWithObjects:@1, @2, @3, @4, @5, nil];// 获取集元素NSArray *objects = [sets allObjects];id obj = nil;// 遍历集元素while ((obj = [enumerator nextObject]) != nil) { NSLog(@"%@", obj);}
- 遍历字典(NSDictionary)
// 初始化字典NSDictionary *infomation = @{@"account" : @"admin", @"password": @123456, @"members" : @YES, @"state" : @"activation"};NSEnumerator *enumerator = [infomation keyEnumerator];id key = nil;// 遍历字典键值对while ((key = [enumerator nextObject]) != nil) { id obj = dicts[key]; NSLog(@"%@ : %@", key, obj);}
- 遍历字典的方式与数组和set略有不同,因为字典里既有键也有值,所以要根据给定的键把对应的值提取出来。使用NSEnumerator还有个好处,就是有多种枚举器可供使用。比如,有反向遍历数组的枚举器,如果拿它来遍历,就可以按反方向来迭代集合中的元素了。
NSArray *numbers = @[@1, @2, @3, @4, @5];NSEnumerator *enumerator = [numbers reverseObjectEnumerator];id obj = nil;while ((obj = [enumerator nextObject]) != nil) { NSLog(@"%@", obj);}// 输出:5 4 3 2 1
快速遍历
快速遍历与使用NSEnumerator来遍历差不多,然而语法更简洁,它为for循环开设了in关键字。这个关键字大幅简化了遍历集合所需的语法。
遍历数组(NSArray)
NSArray *numbers = @[@1, @2, @3, @4, @5];for (id obj in numbers) { NSLog(@"%@", obj);}
- 遍历集(NSSet)
NSSet *sets = [NSSet setWithObjects:@1, @2, @3, @4, @5, nil];for (id obj in sets) { NSLog(@"%@", obj);}
- 遍历字典(NSDictionary)
NSDictionary *infomation = @{@"account" : @"admin", @"password": @123456, @"members" : @YES, @"state" : @"activation"};for (id key in dicts.allKeys) { id obj = dicts[key]; NSLog(@"%@ : %@", key, obj);}
- 由于NSEnumerator对象也实现了NSFastEnumeration协议,所以能用来执行方向遍历。若要反向遍历数组,可采用下面这种写法:
NSArray *numbers = @[@1, @2, @3, @4, @5];for (id obj in [numbers reverseObjectEnumerator]) { NSLog(@"%@", obj);}// 输出:5 4 3 2 1
基于块的遍历方式
在遍历数组及set时,每次迭代都要执行由block参数所传入的块,这个块有三个参数,分别是当前迭代所针对的对象、所针对的下标、以及指向布尔值的指针。前两个参数的含义不言而喻。而通过第三个参数所提供的机制,开发者可以终止遍历操作。
遍历数组(NSArray)
NSArray *numbers = @[@1, @2, @3, @4, @5];[numbers enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { NSLog(@"%@", obj); if (idx == 3) { *stop = YES; }}];
- 遍历集(NSSet)
NSSet *sets = [NSSet setWithObjects:@1, @2, @3, @4, @5, nil];[sets enumerateObjectsUsingBlock:^(id _Nonnull obj, BOOL * _Nonnull stop) { NSLog(@"%@", obj); if(shouldStop) { *stop = YES; }}];
- 遍历字典(NSDictionary)
NSDictionary *infomation = @{@"account" : @"admin", @"password": @123456, @"members" : @YES, @"state" : @"activation"};[infomation enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) { NSLog(@"%@:%@", key, obj); if(shouldStop) { *stop = YES; }}];
通过基于块的遍历方式可以直接从块里获取更多信息。在遍历数组时,可以知道当前所针对的下标。遍历有序set时也一样。而在遍历字典时,无需额外编码,即可同时获取键与值,因而省去了根据给定键来获取对应值这一步。用这种方式遍历字典,可以同时得知键与值,这很可能比其他方式快很多,因为在字典内部的数据结构中,键与值本来就是存储在一起的。
另外一个好处是,能够修改块的方法前面,以免进行类型转换操作,从效果上讲,相当于把本来需要执行的类型转换操作交给块方法签名来做。比方说,要用“快速遍历法”来遍历字典。若已知字典中的对象必须为字符串,则可以这样编码:
for (NSString *key in aDictionary) { NSString *obj = (NSString *)aDictionary[key];}
- 如果改用基于快的方式来遍历,那么就可以在块方法签名中直接转换:
NSDictionary *aDictionary = /* ... */[aDictionary enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSString * _Nonnull obj, BOOL * _Nonnull stop) { // Do something with 'key' and 'obj'}];
- 基于块的遍历方式同样可以执行反向遍历,通过NSEnumeratorReverse选项来实现,要注意:只有在遍历数组或有序set等集合的时候才有意义,此处以数组为例。
NSArray *numbers = @[@1, @2, @3, @4, @5];[numbers enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { NSLog(@"%@", obj);}];// 输出:5 4 3 2 1
要点
遍历集合有四种方式。最基本的是for循环,其次是NSEnumerator遍历法及快速遍历法,最新、最先进的方式则是“块枚举法”。
若提前知道遍历的集合含有何种对象,则应修改块签名,指出对象的具体类型。
- Objective-c:集合类型遍历方法详解
- Objective-c:集合类型
- Objective-C枚举类型详解
- Objective-C 方法类型限定
- Objective C中id类型详解
- #Objective - C - sixth-Day 数组排序及集合遍历
- Objective-C集合遍历的几种方式
- [Objective-C]Class类型、class方法
- [Objective-C]Class类型、class方法
- [Objective-C]Class类型、class方法
- Objective-C 【动态类型检测&响应方法】
- [Objective-C]Class类型、class方法
- 【C#】遍历各类数据集合的方法
- 【Objective-C】OC中的Dealloc方法详解
- [Objective-C]OC中的Dealloc方法详解
- Objective C 方法和变量详解
- Objective-C方法的调用流程详解
- Objective-c 字符串遍历
- html文件查看器2
- Lua封装将数字转换成万显示
- layer.js
- 递归求解细胞分裂问题
- 独立日记 2015年12月29日 day8 第一周总结
- Objective-c:集合类型遍历方法详解
- Bean Validation 介绍及最佳实践
- 如何在Swift中使用SELECTOR
- Linux Mint(系统更新)
- Linux技术——常用 linux 命令
- CSS之Flexbox布局
- 查看MYSQL数据库中所有用户及拥有权限
- 用来创建对象的设计模式之抽象工厂模式
- 大数据分析工具