数组可对其中包含的元素进行排序。
在排序前,我们需要定义一个Model类,将Model类对象添加至数组中。
定义一个简单的Model类
// Model.h@interfaceModel:NSObject@property(nonatomic,copy)NSString*name;@property(nonatomic,assign)BOOLsex;@property(nonatomic,assign)doubleheight;@property(nonatomic,assign)intage;@end// Model.m@implementationModel@end
生成假数据:
NSArray *nameArray = @[@"小白", @"大白", @"老白", @"艾尔", @"黑山", @"张三", @"李四", @"王五", @"范晶", @"荆南", @"昔日", @"安安"]; NSArray *ageArray = @[@3, @32, @45, @22, @32, @27, @15, @22, @55, @34, @32, @22]; NSArray *heightArray = @[@100, @166, @180, @165, @163, @176, @174, @183, @186, @178, @167, @160]; NSMutableArray *originalArray = [NSMutableArrayarrayWithCapacity:nameArray.count];for(int i =0; i
输出数组元素
// 输出数组元素 for(Model *modelinoriginalArray) {NSLog(@"age: %d,height: %.1f name: %@", model.age,model.height, model.name); }/*
age: 3 ,height: 100.0 name: 小白
age: 32,height: 166.0 name: 大白
age: 45,height: 180.0 name: 老白
age: 22,height: 165.0 name: 艾尔
age: 32,height: 163.0 name: 黑山
age: 27,height: 176.0 name: 张三
age: 15,height: 174.0 name: 李四
age: 22,height: 183.0 name: 王五
age: 55,height: 186.0 name: 范晶
age: 34,height: 178.0 name: 荆南
age: 32,height: 167.0 name: 昔日
age: 22,height: 160.0 name: 安安
*/
倒序
在Array的扩展类(NSExtendedArray)中提供了reverseObjectEnumerator方法
- (NSEnumerator *)reverseObjectEnumerator;
上述方法的返回值为NSEnumerator类对象。通过NSEnumerator的扩展类(NSExtendedEnumerator)中的allObjects属性,将其转化为Array类对象。
@interfaceNSEnumerator (NSExtendedEnumerator)@property(readonly,copy)NSArray *allObjects;@end
使用范例
//倒序originalArray = (NSMutableArray*)[[originalArray reverseObjectEnumerator] allObjects];
输出排序结果
// 输出排序结果for(Model *modelinoriginalArray) {NSLog(@"age: %d,height: %.1f name: %@", model.age,model.height, model.name);}/*
age: 22,height: 160.0 name: 安安
age: 32,height: 167.0 name: 昔日
age: 34,height: 178.0 name: 荆南
age: 55,height: 186.0 name: 范晶
age: 22,height: 183.0 name: 王五
age: 15,height: 174.0 name: 李四
age: 27,height: 176.0 name: 张三
age: 32,height: 163.0 name: 黑山
age: 22,height: 165.0 name: 艾尔
age: 45,height: 180.0 name: 老白
age: 32,height: 166.0 name: 大白
age: 3 ,height: 100.0 name: 小白
*/
升序/ 降序
1. sortedArrayUsingSelector & sortUsingSelector
NSArray的排序方法(sortedArrayUsingSelector:)是生成一个排好序的新数组。
NSMutableArray的排序可以直接对该数组进行排序(sortUsingSelector:),也可以生成新数组(sortedArrayUsingSelector: ),而原数组不变。
数组元素为字符串或基本数据类型时,可直接使用系统定义的函数进行排序
NSString类具有(compare:)(caseInsensitiveCompare:)(localizedStandardCompare:)方法。
compare:区分大小写
caseInsensitiveCompare: 不区分大小写
localizedStandardCompare:根据当前语言环境的语言规则进行排序(语言环境可能会根据大小写,变音符号等等的顺序而发生改变)
基本数据类型如int, double等, 可使用NSNumber类具有的(compare:)方法。
使用范例:
字符串数组
//字符串数组NSMutableArray*newNameArray = [NSMutableArrayarrayWithArray:nameArray];[newNameArray addObjectsFromArray:@[@"Smith",@"Bohn",@"aohn",@"john"]];NSArray*resultNameArray = [newNameArray sortedArrayUsingSelector:@selector(localizedStandardCompare:)];
// 输出排序结果for(NSString*nameinresultNameArray) {NSLog(@"name: %@",name);}/** //字符串数组
name: 艾尔
name: 安安
name: 大白
name: 范晶
name: 黑山
name: 荆南
name: 老白
name: 李四
name: 王五
name: 昔日
name: 小白
name: 张三
name: aohn
name: Bohn
name: john
name: Smith
name: Smith你好
注:先按拼音排序 在按字母排序 不分大小写
*/
int类型数组
//int类型数组NSArray*resultAgeArray = [ageArray sortedArrayUsingSelector:@selector(compare:)];
// 输出排序结果for(NSNumber*ageinresultAgeArray) {NSLog(@"age: %@",age);}/**
//int类型数组
age: 3
age: 15
age: 22
age: 22
age: 22
age: 27
age: 32
age: 32
age: 32
age: 34
age: 45
age: 55
*/
数组元素为模型对象或字典类型时,需要自定义排序方法
自定义Mode扩展类并添加自定义方法
// NSNumber+compare.h@interfaceModel(compare)- (NSComparisonResult)compareName:(Model *)otherModel;- (NSComparisonResult)compareAge:(Model *)otherModel;@end// NSNumber+compare.m@implementationModel(compare)- (NSComparisonResult)compareName:(Model *)otherModel{NSComparisonResultresult = [self.name localizedStandardCompare:otherModel.name];returnresult ==NSOrderedDescending;// 升序// return result == NSOrderedSame; // 不变// return result == NSOrderedAscending; // 降序}- (NSComparisonResult)compareAge:(Model *)otherModel{NSNumber*number1 = [NSNumbernumberWithInt:self.age];NSNumber*number2 = [NSNumbernumberWithInt:otherModel.age];NSComparisonResultresult = [number1 compare:number2];returnresult ==NSOrderedDescending;// 升序// return result == NSOrderedSame; // 不变// return result == NSOrderedAscending; // 降序}@end
注:自定义方法返回值必须为NSComparisonResult类型
使用范例
根据name属性进行排序
//根据name属性进行排序 NSArray*resultStrArray = [originalArray sortedArrayUsingSelector:@selector(compareName:)];
// 输出排序结果for(Model *modelinresultStrArray) {NSLog(@"age: %d,height: %.1f name: %@", model.age,model.height, model.name); }/**
age: 22,height: 165.0 name: 艾尔
age: 22,height: 160.0 name: 安安
age: 32,height: 166.0 name: 大白
age: 55,height: 186.0 name: 范晶
age: 32,height: 163.0 name: 黑山
age: 34,height: 178.0 name: 荆南
age: 45,height: 180.0 name: 老白
age: 15,height: 174.0 name: 李四
age: 22,height: 183.0 name: 王五
age: 32,height: 167.0 name: 昔日
age: 3 ,height: 100.0 name: 小白
age: 27,height: 176.0 name: 张三
*/
根据age属性进行排序
//根据age属性进行排序NSArray*resultNumArray = [originalArray sortedArrayUsingSelector:@selector(compareAge:)];
// 输出排序结果for(Model *modelinresultNumArray) {NSLog(@"age: %d,height: %.1f name: %@", model.age,model.height, model.name); }/**
age: 3 ,height: 100.0 name: 小白
age: 15,height: 174.0 name: 李四
age: 22,height: 165.0 name: 艾尔
age: 22,height: 183.0 name: 王五
age: 22,height: 160.0 name: 安安
age: 27,height: 176.0 name: 张三
age: 32,height: 166.0 name: 大白
age: 32,height: 163.0 name: 黑山
age: 32,height: 167.0 name: 昔日
age: 34,height: 178.0 name: 荆南
age: 45,height: 180.0 name: 老白
age: 55,height: 186.0 name: 范晶
*/
2.sortedArrayUsingComparator & sortUsingComparator
NSArray的排序方法(sortedArrayUsingComparator:)是生成一个排好序的新数组。
NSMutableArray的排序可以直接对该数组进行排序(sortUsingComparator:),也可以生成新数组(sortedArrayUsingComparator: ),而原数组不变。
如果待比较的属性是字符串(NSString)类型, 使用其默认的方法: localizedStandardCompare: 它将根据当前语言环境的语言规则进行排序(语言环境可能会根据大小写,变音符号等等的顺序而发生改变)
//如果待比较的属性是字符串(NSString)类型, 使用其默认的方法: localizedStandardCompare: 它将根据当前语言环境的语言规则进行排序(语言环境可能会根据大小写,变音符号等等的顺序而发生改变)NSArray*resultStrArray = [originalArray sortedArrayUsingComparator:^NSComparisonResult(idobj1,idobj2) { Model *model1 = obj1; Model *model2 = obj2;NSComparisonResultresult = [model1.name localizedStandardCompare:model2.name];returnresult ==NSOrderedDescending;// 升序// return result == NSOrderedSame; // 不变// return result == NSOrderedAscending; // 降序}];
// 输出排序结果for(Model *modelinresultStrArray) {NSLog(@"age: %d,height: %.1f name: %@", model.age,model.height, model.name); }/**
如果待比较的属性是字符串(NSString)类型, 使用其默认的方法: localizedStandardCompare: 它将根据当前语言环境的语言规则进行排序(语言环境可能会根据大小写,变音符号等等的顺序而发生改变)
age: 22,height: 165.0 name: 艾尔
age: 22,height: 160.0 name: 安安
age: 32,height: 166.0 name: 大白
age: 55,height: 186.0 name: 范晶
age: 32,height: 163.0 name: 黑山
age: 34,height: 178.0 name: 荆南
age: 45,height: 180.0 name: 老白
age: 15,height: 174.0 name: 李四
age: 22,height: 183.0 name: 王五
age: 32,height: 167.0 name: 昔日
age: 3,height: 100.0 name: 小白
age: 27,height: 176.0 name: 张三
*/
如果待比较的属性是其他的类型, 比如int, double等, 就需要对将其转化为NSNumber类型;
//如果待比较的属性是其他的类型, 比如int, double等, 就需要对将其转化为NSNumber类型;NSArray*resultNumArray = [originalArray sortedArrayUsingComparator:^NSComparisonResult(idobj1,idobj2) { Model *model1 = obj1; Model *model2 = obj2;NSNumber*number1 = [NSNumbernumberWithInt:model1.age];NSNumber*number2 = [NSNumbernumberWithInt:model2.age];NSComparisonResultresult = [number1 compare:number2];returnresult ==NSOrderedDescending;// 升序// return result == NSOrderedSame; // 不变// return result == NSOrderedAscending; // 降序}];
// 输出排序结果for(Model *modelinresultNumArray) {NSLog(@"age: %d,height: %.1f name: %@", model.age,model.height, model.name); }/**
//如果待比较的属性是其他的类型, 比如int, double等, 就需要对将其转化为NSNumber类型;
age: 3 ,height: 100.0 name: 小白
age: 15,height: 174.0 name: 李四
age: 22,height: 165.0 name: 艾尔
age: 22,height: 183.0 name: 王五
age: 22,height: 160.0 name: 安安
age: 27,height: 176.0 name: 张三
age: 32,height: 166.0 name: 大白
age: 32,height: 163.0 name: 黑山
age: 32,height: 167.0 name: 昔日
age: 34,height: 178.0 name: 荆南
age: 45,height: 180.0 name: 老白
age: 55,height: 186.0 name: 范晶
*/
3. sortedArrayWithOptions: usingComparator & sortWithOptions: usingComparator
NSArray的排序方法(sortedArrayWithOptions: usingComparator: )是生成一个排好序的新数组。
NSMutableArray的排序可以直接对该数组进行排序(sortWithOptions: usingComparator: ),也可以生成新数组(sortedArrayWithOptions: usingComparator: ),而原数组不变。
参数解释
opts : 枚举类型NSSortOptions(NSSortStable,NSSortConcurrent), 其中NSSortStable 更稳定,但是效率低,比较时是串行操作。NSSortConcurrent 比较时是并行操作,效率高,适合排序大规模数据。通常我们使用NSSortStable。快点这里哦
cmptr :NSComparator比较器,block方法, 可以在其中指定比较规则,返回值为NSComparisonResult
如果待比较的属性是字符串(NSString)类型, 使用其默认的方法: localizedStandardCompare: 它将根据当前语言环境的语言规则进行排序(语言环境可能会根据大小写,变音符号等等的顺序而发生改变)
//如果待比较的属性是字符串(NSString)类型, 使用其默认的方法: localizedStandardCompare: 它将根据当前语言环境的语言规则进行排序(语言环境可能会根据大小写,变音符号等等的顺序而发生改变)NSArray*resultStrArray = [originalArray sortedArrayWithOptions:NSSortStableusingComparator:^NSComparisonResult(id_Nonnull obj1,id_Nonnull obj2) { Model *model1 = obj1; Model *model2 = obj2;NSComparisonResultresult = [model1.name localizedStandardCompare:model2.name];returnresult ==NSOrderedDescending;// 升序// return result == NSOrderedSame; // 不变// return result == NSOrderedAscending; // 降序}];
// 输出排序结果for(Model *modelinresultStrArray) {NSLog(@"age: %d,height: %.1f name: %@", model.age,model.height, model.name); }/**
如果待比较的属性是字符串(NSString)类型, 使用其默认的方法: localizedStandardCompare: 它将根据当前语言环境的语言规则进行排序(语言环境可能会根据大小写,变音符号等等的顺序而发生改变)
age: 22,height: 165.0 name: 艾尔
age: 22,height: 160.0 name: 安安
age: 32,height: 166.0 name: 大白
age: 55,height: 186.0 name: 范晶
age: 32,height: 163.0 name: 黑山
age: 34,height: 178.0 name: 荆南
age: 45,height: 180.0 name: 老白
age: 15,height: 174.0 name: 李四
age: 22,height: 183.0 name: 王五
age: 32,height: 167.0 name: 昔日
age: 3,height: 100.0 name: 小白
age: 27,height: 176.0 name: 张三
*/
如果待比较的属性是其他的类型, 比如int, double等, 就需要对将其转化为NSNumber类型;
//如果待比较的属性是其他的类型, 比如int, double等, 就需要对将其转化为NSNumber类型;NSArray*resultNumArray = [originalArray sortedArrayWithOptions:NSSortStableusingComparator:^NSComparisonResult(id_Nonnull obj1,id_Nonnull obj2) { Model *model1 = obj1; Model *model2 = obj2;NSNumber*number1 = [NSNumbernumberWithInt:model1.age];NSNumber*number2 = [NSNumbernumberWithInt:model2.age];NSComparisonResultresult = [number1 compare:number2];returnresult ==NSOrderedDescending;// 升序// return result == NSOrderedSame; // 不变// return result == NSOrderedAscending; // 降序}];
// 输出排序结果for(Model *modelinresultNumArray) {NSLog(@"age: %d,height: %.1f name: %@", model.age,model.height, model.name); }/**
//如果待比较的属性是其他的类型, 比如int, double等, 就需要对将其转化为NSNumber类型;
age: 3 ,height: 100.0 name: 小白
age: 15,height: 174.0 name: 李四
age: 22,height: 165.0 name: 艾尔
age: 22,height: 183.0 name: 王五
age: 22,height: 160.0 name: 安安
age: 27,height: 176.0 name: 张三
age: 32,height: 166.0 name: 大白
age: 32,height: 163.0 name: 黑山
age: 32,height: 167.0 name: 昔日
age: 34,height: 178.0 name: 荆南
age: 45,height: 180.0 name: 老白
age: 55,height: 186.0 name: 范晶
*/
4. sortedArrayUsingDescriptors & sortUsingDescriptors
NSArray的排序方法(sortedArrayUsingDescriptors:)是生成一个排好序的新数组。
NSMutableArray的排序可以直接对该数组进行排序(sortUsingDescriptors:),也可以生成新数组(sortedArrayUsingDescriptors: ),而原数组不变。
+ (instancetype)sortDescriptorWithKey:(nullableNSString*)key ascending:(BOOL)ascendingNS_AVAILABLE(10_6,4_0);+ (instancetype)sortDescriptorWithKey:(nullableNSString*)key ascending:(BOOL)ascending selector:(nullableSEL)selectorNS_AVAILABLE(10_6,4_0);// keys may be key paths- (instancetype)initWithKey:(nullableNSString*)key ascending:(BOOL)ascending;- (instancetype)initWithKey:(nullableNSString*)key ascending:(BOOL)ascending selector:(nullableSEL)selector;+ (instancetype)sortDescriptorWithKey:(nullableNSString*)key ascending:(BOOL)ascending comparator:(NSComparator)cmptrNS_AVAILABLE(10_6,4_0);- (instancetype)initWithKey:(nullableNSString*)key ascending:(BOOL)ascending comparator:(NSComparator)cmptrNS_AVAILABLE(10_6,4_0);
使用范例
//创建排序规则NSSortDescriptor//key :按照age属性 升序排序NSSortDescriptor*sort = [NSSortDescriptorsortDescriptorWithKey:@"age"ascending:YES];//给数组添加排序规则[originalArray sortUsingDescriptors:@[sort]];
// 输出排序结果for(Model *modelinoriginalArray) {NSLog(@"age: %d,height: %.1f name: %@", model.age,model.height, model.name);}/**
age: 3 ,height: 100.0 name: 小白
age: 15,height: 174.0 name: 李四
age: 22,height: 165.0 name: 艾尔
age: 22,height: 183.0 name: 王五
age: 22,height: 160.0 name: 安安
age: 27,height: 176.0 name: 张三
age: 32,height: 166.0 name: 大白
age: 32,height: 163.0 name: 黑山
age: 32,height: 167.0 name: 昔日
age: 34,height: 178.0 name: 荆南
age: 45,height: 180.0 name: 老白
age: 55,height: 186.0 name: 范晶
*/
可同时指定多个规则:其优先级取决于在数组中的先后顺序
//创建排序规则NSSortDescriptor//key :按照age属性 升序排序NSSortDescriptor*sort = [NSSortDescriptorsortDescriptorWithKey:@"age"ascending:YES];//age 相同 按照height属性 升序排序NSSortDescriptor*sort1 = [NSSortDescriptorsortDescriptorWithKey:@"height"ascending:YES];//给数组添加排序规则[originalArray sortUsingDescriptors:@[sort,sort1]];
// 输出排序结果for(Model *modelinoriginalArray) {SLog(@"age: %d,height: %.1f name: %@", model.age,model.height, model.name);}/**
age: 3 ,height: 100.0 name: 小白
age: 15,height: 174.0 name: 李四
age: 22,height: 160.0 name: 安安
age: 22,height: 165.0 name: 艾尔
age: 22,height: 183.0 name: 王五
age: 27,height: 176.0 name: 张三
age: 32,height: 163.0 name: 黑山
age: 32,height: 166.0 name: 大白
age: 32,height: 167.0 name: 昔日
age: 34,height: 178.0 name: 荆南
age: 45,height: 180.0 name: 老白
age: 55,height: 186.0 name: 范晶
*//** 其中age相同的按照height属性 升序排序
age: 22,height: 160.0 name: 安安
age: 22,height: 165.0 name: 艾尔
age: 22,height: 183.0 name: 王五
age: 32,height: 163.0 name: 黑山
age: 32,height: 166.0 name: 大白
age: 32,height: 167.0 name: 昔日
*/
注:关于NSSortDescriptor类更详细的排序使用,请参考iOS - 排序: NSSortDescriptor
5. sortedArrayUsingFunction:context & sortedArrayUsingFunction:context:hint & sortUsingFunction:context & sortUsingFunction:context:hint
NSArray的排序方法(sortedArrayUsingFunction:context:)与(sortedArrayUsingFunction:context:hint:)是生成一个排好序的新数组。
NSMutableArray的排序可以直接对该数组进行排序(sortUsingFunction:context:)与(sortUsingFunction:context:hint:),也可以生成新数组(sortedArrayUsingFunction:context:)与(sortedArrayUsingFunction:context:hint:),而原数组不变。
参数解释
comparator:基于函数指针的自定义函数
context:上下文,通常为NuLL
hint:加速排序,同sortedArrayHint
注:hinted sort 方式在你有一个已排序的大数组 (N 个元素) 并且只改变其中一小部分(P 个添加和删除,这里 P远小于 N)时,会非常有效。你可以重用原来的排序结果,然后在 N 个老项目和 P 个新项目进行一个概念上的归并排序。为了得到合适的 hint,你应该在原来的数组排序后使用 sortedArrayHint 来在你需要的时候(比如在数组改变后想重新排序时)保证持有它。
使用范例
定义一个函数方法
NSIntegercompareByAge(idobj1,idobj2,void*context){ Model *model1 = obj1; Model *model2 = obj2;NSNumber*number1 = [NSNumbernumberWithInt:model1.age];NSNumber*number2 = [NSNumbernumberWithInt:model2.age];NSComparisonResultresult = [number1 compare:number2];returnresult ==NSOrderedDescending;// 升序// return result == NSOrderedSame; // 不变// return result == NSOrderedAscending; // 降序}
排序
NSArray*resultNumArray = [originalArray sortedArrayUsingFunction:compareByAge context:nil];
// 输出排序结果for(Model *modelinresultNumArray) {NSLog(@"age: %d,height: %.1f name: %@", model.age,model.height, model.name); }/**
age: 3 ,height: 100.0 name: 小白
age: 15,height: 174.0 name: 李四
age: 22,height: 165.0 name: 艾尔
age: 22,height: 183.0 name: 王五
age: 22,height: 160.0 name: 安安
age: 27,height: 176.0 name: 张三
age: 32,height: 166.0 name: 大白
age: 32,height: 163.0 name: 黑山
age: 32,height: 167.0 name: 昔日
age: 34,height: 178.0 name: 荆南
age: 45,height: 180.0 name: 老白
age: 55,height: 186.0 name: 范晶
*/
总结
数组元素为字符串或基本数据类型时,推荐使用系统定义的函数进行排序sortedArrayUsingSelector & sortUsingSelector
需要通过多个key进行排序时,推荐使用sortedArrayUsingDescriptors & sortUsingDescriptors
比较方法复杂时,推荐使用sortedArrayWithOptions: usingComparator & sortWithOptions: usingComparator或sortedArrayUsingComparator & sortUsingComparator
链接:https://www.jianshu.com/p/2fa53fa56dcc