`
bluefivecn
  • 浏览: 11675 次
  • 性别: Icon_minigender_1
  • 来自: 天津
社区版块
存档分类
最新评论

更多NSArray排序

阅读更多
http://blog.ablepear.com/2011/12/objective-c-tuesdays-more-nsarray.html

上次我们讲了C数组和NSArray排序,今天我们继续讲讲使用NSSortDescriptors为NSArray排序.

NSArray要求指定比较函数来完成排序.当为一些简单类型(NSString, NSDate)NSArray排序的时候,比较函数十分容易编写,并且一些普通对象都有比较函数,像-caseInsensitiveCompare: 和 -localizedCompare:.

当为复杂类型NSArray排序的时候,编写比较函数就更麻烦并且更易出错.这是Person类的接口:
// Person.h
@interface Person : NSObject

@property (strong) Address *address;
@property (strong) NSDate *birthdate;
@property (copy) NSString *firstName;
@property (copy) NSString *lastName;

@end

这是Person要使用的Address类的接口:
// Address.h
@interface Address : NSObject

@property (copy, nonatomic) NSString *street;
@property (copy, nonatomic) NSString *city;
@property (copy, nonatomic) NSString *state;
@property (copy, nonatomic) NSString *country;
@property (copy, nonatomic) NSString *postalCode;

@end

我们有一个Person的NSArray,我们要按country,lastName,firstName来给它排序.这是用比较block的一种实现方式:
// sort Person objects by lastName, firstName
Person *frodo = [Person new];
[frodo setFirstName:@"Frodo"];
[frodo setLastName:@"Baggins"];
// ...
[[frodo address] setCountry:@"Shire"];

Person *bilbo = [Person new];
[bilbo setFirstName:@"Bilbo"];
[bilbo setLastName:@"Baggins"];
// ...
[[bilbo address] setCountry:@"Shire"];

Person *legolas = [Person new];
[legolas setFirstName:@"Legolas"];
[legolas setLastName:@"Greenleaf"];
// ...
[[legolas address] setCountry:@"Mirkwood"];

NSArray *people = [NSArray arrayWithObjects:frodo, bilbo, legolas, nil];
NSArray *sortedPeople = [people sortedArrayUsingComparator:^(id item1, id item2) {
  Person *person1 = item1;
  Person *person2 = item2;
  
  // NSComparisonResult is a typedef for int
  NSComparisonResult result = [[[person1 address] country] compare:[[person2 address] lastName]];
  if (result) {
    return result;
  }
  
  result = [[person1 lastName] compare:[person2 lastName]];
  if (result) {
    return result;
  }
  
  result = [[person1 firstName] compare:[person2 firstName]];
  if (result) {
    return result;
  }
  
  return NSOrderedSame; // NSOrderedSame == 0
}];
// sortedPeople contains:
// Legolas Greenleaf (Mirkwood)
// Bilbo Baggins (Shire)
// Frodo Baggins (Shire)

多字段比较的通用模式是简单的,依次检查每个字段,如果比较结果不是0,停止并返回比较结果;如果所有字段都相等,返回0(或者用更具描述性的NSOrderedSame).如果你需要深入子孙对象去检查字段,这会变得非常繁琐.

幸运的是有简单的方法解决这个问题.NSArray有一个叫-sortedArrayUsingDescriptors:的方法,它接收一组NSSortDescriptor 对象作为参数.每个NSSortDescriptor 对象指定一个key路径和排序方向(升序或者降序)。数组中NSSortDescriptors的顺序决定每个字段的优先级.如果你不熟悉KVC(Key Value Coding),你可能没有遇到过key路径.KVC允许你用字符型的字段名称来get,set对象字段.访问子孙对象的字段,你需要使用.分隔的key组成的key路径.KVC有很多有意思的东西,但今天我们只涉及构建一组NSSortDescriptors:
NSSortDescriptor *byCountry = [NSSortDescriptor sortDescriptorWithKey:@"address.country" 
                                                            ascending:YES];
NSSortDescriptor *byLastName = [NSSortDescriptor sortDescriptorWithKey:@"lastName" 
                                                             ascending:YES];
NSSortDescriptor *byFirstName = [NSSortDescriptor sortDescriptorWithKey:@"firstName" 
                                                              ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObjects:byCountry, byLastName, byFirstName, nil];

注意byCountry 排序描述符用key路径@"address.country":,它首先取得Person对象的address属性值,然后取得address的country属性值.Key路径可以任意深.

使用排序描述符组是简单的:
NSArray *sortedPeople = [people sortedArrayUsingDescriptors:sortDescriptors];
// sortedPeople contains:
// Legolas Greenleaf (Mirkwood)
// Bilbo Baggins (Shire)
// Frodo Baggins (Shire)

这使用创建复杂的排序规则变得容易,并且你不再受限于字段的缺省比较函数.你可以为一个比较函数指定一个selector:
// specify a method to call on the lastName object
NSSortDescriptor *byLastName = [NSSortDescriptor sortDescriptorWithKey:@"lastName" 
                                                             ascending:YES
                                                              selector:@selector(caseInsensitiveCompare:)];

或者为了更专门的比较,你可以传递NSComparator的block:
// sort descriptor using length of last name
NSSortDescriptor *byLastNameLength = [NSSortDescriptor sortDescriptorWithKey:@"lastName" 
                                                                   ascending:YES 
                                                                  comparator:^(id item1, id item2) {
  NSString *lastName1 = item1;
  NSString *lastName2 = item2;
  // cast result to NSComparisonResult so that the 
  // compiler infers the correct return type
  return (NSComparisonResult) ([lastName1 length] - [lastName2 length]);
}];

用NSSortDescriptors 指定复杂排序规则是比较易读易写易维护的声明代码,并且大多数情况你你都应该考虑使用NSSortDescriptor,而不是自己编写比较函数.
分享到:
评论

相关推荐

    NSArray排序demo

    这些代码示例通常会包括创建一个未排序的数组,然后使用上述方法之一对其进行排序,并显示排序后的结果,以便更好地理解和学习`NSArray`的排序机制。 总之,`NSArray`的排序可以通过多种方式实现,包括`...

    oc中数组排序

    1. NSArray排序:由于NSArray本身不支持排序,如果需要对NSArray进行排序,通常会先将其转换为可变数组NSMutableArray,进行排序后再转回NSArray。 2. NSMutableArray排序:提供了`sortUsingComparator:`和`...

    ios开发多种排序法

    在这种情况下,可以在比较器中添加更多的判断: ```swift let sortedPeople = people.sorted { (p1, p2) in if p1.age == p2.age { return p1.name 当年龄相同时,按名字排序 } else { return p1.age 首先按...

    对半查找,选择排序,冒泡排序和快速排序的Objective-C实现

    冒泡排序是另一种简单的排序算法,它重复地遍历待排序的序列,比较每对相邻元素,然后交换位置,直到没有更多的交换,即序列已排序。Objective-C的实现如下: ```objc - (void)bubbleSort:(NSMutableArray *)array ...

    IOS根据汉字(或英文)按字母排序并按首字母分组

    在iOS开发中,经常需要对汉字或英文名称的数组进行排序和分组,以便于用户更方便地查找和浏览。这个任务通常涉及到Objective-C(OC)编程语言的使用,因此我们今天将深入探讨如何在iOS应用中实现这个功能。 首先,...

    非常棒的模块拖动 移动 app管理 排序

    这需要额外的数据结构来管理不同类别,同时在拖动时,图标不仅可以改变位置,还可以改变所属的分类,这需要更复杂的数据操作和界面更新逻辑。 总的来说,这个项目涵盖了iOS开发中的手势识别、数据模型同步、自定义...

    ios-汉字排序.zip

    如果这是一个示例项目,通过查看和学习源代码,我们可以更深入地理解如何在实践中解决汉字排序问题。 总的来说,“ios-汉字排序.zip”提供的资源对于了解和实践iOS中的汉字排序是一个宝贵的工具。通过学习和应用...

    iOS汉字按首字母排序的开源库

    而这个开源库提供了一个解决方案,它可能包含一个或多个类,如`Pinyin`类,包含`convertToPinyin`这样的方法,用于将汉字转换为拼音,然后可以根据拼音的首字母进行排序。 在给出的压缩包文件名`pinyin.h`和`pinyin...

    Object-C数组排序

    当需要根据多个属性进行排序时,可以使用`sortUsingDescriptors:`方法,它接受一个NSArray对象,其中包含NSSortDescriptor对象,每个描述符代表一种排序方式。例如: ```objc NSMutableArray *descriptors = @[ ...

    iOS 对NSMutableArray进行排序和过滤的实例

    然后,我们将`sortDescriptor`添加到一个`NSArray`中,这样我们可以传递多个排序规则: ```objc NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil]; ``` 最后,使用`...

    ios-iOS类目常用类目.zip

    1. 扩展系统类的功能,如上述的NSArray排序方法。 2. 给私有分类添加辅助方法,以提高代码组织的清晰度。 3. 在没有权限修改源码的第三方库中添加功能或修复问题。 4. 实现一些常用的工具方法,如字符串转日期、颜色...

    iOS对数组进行排序的实例代码

    排序方法的选择取决于你的需求:如果你不想改变原数组,或者需要根据多个属性进行复杂排序,那么`NSArray`的`sortedArrayUsingDescriptors:`更适合;如果你需要就地排序,并且数组可以被修改,`NSMutableArray`的`...

    LHQListSort.zip

    "LHQListSort.zip"文件可能包含了如何在iOS应用中实现自定义排序功能,特别是针对包含多音字情况的特殊处理。以下是对这一主题的详细讲解: 首先,数据排序在iOS中通常是基于数组的。假设我们有一个包含模型对象的...

    iOS实现联系人按照首字母进行排序的实例

    在iOS开发中,实现联系人按照首字母进行排序是一个常见的需求,这有助于用户更方便地查找和管理他们的联系人列表。`UILocalizedIndexedCollation`是苹果提供的一种内置的排序机制,它允许开发者轻松地根据字符的首...

    IOS应用源码之Array.rar

    这个“IOS应用源码之Array.rar”文件很可能包含了一个或多个示例项目,用于演示如何在iOS应用中使用NSArray及其相关的类,如NSMutableArray。 NSArray是一个不可变的集合,意味着一旦创建,就不能更改其内容。它...

    PinYinPaiXu

    - **数据展示**:在列表或表格视图中,显示数据时,可以先对数据进行拼音排序,提供更好的用户体验。 - **搜索优化**:在搜索功能中,预处理数据并按拼音排序,可以提高搜索速度。 5. **注意事项** - **多音字...

    iOS 通讯录及tableViewCell中多音字的解决办法demo

    在获取到联系人的名字拼音后,可以利用NSArray的sortedArrayUsingComparator方法进行排序,根据拼音首字母进行升序排列。 在UITableViewCell中展示数据时,我们可以创建一个自定义的UITableViewCell子类,用于显示...

    Objective-C 经典字典数组排序 - 省市区

    在实际开发中,可能还需要处理更复杂的情况,例如考虑排序规则(如拼音排序)、处理缺失数据等。同时,为了提高性能,可以考虑使用`NSOrderedSet`代替`NSArray`,或者在现代版本的iOS中使用`Swift`,利用其更强大的...

    oc-数组倒叙

    在Objective-C(简称OC)中,数组是一种常用的数据结构,用于存储多个有序的元素。当你需要将数组中的元素顺序反转,即实现数组的倒序,可以采用多种方法。本篇文章将详细讲解如何在OC中实现数组倒序的操作。 首先...

    基于FMDB数据库操作类PYFMDB.zip

    //取第一页,每页10条按条件查询数据,指定字段,设置分页,设置排序,返回结果为NSArray 排序中 desc 代表 降序,asc代表升序 单个字段排序 如 id desc 多个字段排序 如 id,wheel ascNSString *where = @"name='...

Global site tag (gtag.js) - Google Analytics