OC中的NSArray提供了较多的排序方法,可以对数组元素进行有效的排序,下面先准备一个Student和Course类来作为练习对象。
一 创建练习类
1 Course类
// Course.h
#import <Foundation/Foundation.h>
@interface Course : NSObject
/** 初始化Course类的类方法*/
+ (instancetype)courseWithEnglish:(float)englishRecords
Chinese:(float)chineseRecords;
/** > 英语成绩*/
@property (nonatomic, assign) float englishRecords;
/** > 汉语成绩*/
@property (nonatomic, assign) float chineseRecords;
@end
// Course.m
#import "Course.h"
@implementation Course
#pragma mark 实现初始化类方法
+ (instancetype)courseWithEnglish:(float)englishRecords Chinese:(float)chineseRecords {
Course *course = [[[Course alloc] init] autorelease];
course.english = englishRecords;
course.chinese = chineseRecords;
return course;
}
2 Student类
// Student.h
#import <Foundation/Foundation.h>
@interface Student : NSObject
@class Course;
/** 通过姓名初始化学生的静态方法*/
+ (instancetype)studentWithName:(NSString *)name;
/** 通过姓名和课程初始化学生的静态方法*/
+ (instancetype)studentWithName:(NSString *)name course:(Course *)course;
/** > 学生姓名*/
@property (nonatomic, retain) NSString *name;
/** > 学生课程*/
@property (nonatomic, retain) Course *course;
@end
// Student.m
#import "Student.h"
#import "Course.h"
@implementation Student
#pragma mark 实现Student初始化静态方法-姓名
+ (instancetype)studentWithName:(NSString *)name {
Student *student = [[[Student alloc] init] autorelease];
student.name = name;
return student;
}
#pragma mark 实现Student初始化静态方法-姓名&课程
+ (instancetype)studentWithName:(NSString *)name course:(Course *)course {
Student *student = [self studentWithName:name];
student.course = course;
return student;
}
#pragma mark Student description方法
- (NSString *)description {
return [NSString stringWithFormat:@"Name:%@, English:%.2f, Chinese:%.2f",
_name, _course.englishRecords, _course.chineseRecords];
}
#pragma mark - Student回收方法
- (void)dealloc {
[_name release];
[_course release];
NSLog(@"%@ 对象已销毁", self.name);
[super dealloc];
}
二 实现排序
1 sortedArrayUsingComparator
sortedArrayUsingComparator是NSArray中的排序方法之一,该方法实际是应用了OC中的block语法。在NSMutableArray中,还有一个sortUsingComparator方法,因为NSMutableArray是可变数组,所以该方法是对原数组进行排序,而sortedArrayUsingComparator方法则是返回一个完成排序的新数组,原数组保持不变。这有点类似于Python中list的sort和sorted方法。
假如现在有一个存放了Student对象的数组,需要对数组中的元素根据Student的姓名进行排序,那么可以采用以下方法:
void sortArrayByComparator() {
// 创建Student对象
Student *student1 = [Student studentWithName:@"zhangsan"];
Student *student2 = [Student studentWithName:@"lisi"];
Student *student3 = [Student studentWithName:@"wanwu"];
// 将对象添加到数组
NSArray *studentArray = [NSArray arrayWithObjects:student1, student2, student3, nil];
NSArray *sortedArray = [studentArray sortedArrayUsingComparator:
^NSComparisonResult(id obj1, id obj2) {// 参数也可直接写为(Student *stu1, Student *stu2)
Student *stu1 = (Student *)obj1;
Student *stu2 = (Student *)obj2;
// 返回的是NSComparisonResult类型:
// 1)NSOrderedAscending 升序,代表stu1.name < stu2.name
// 2)NSOrderedSame 相等,代表stu1.name = stu2.name
// 3)NSOrderedDescending 降序,代表stu1.name > stu2.name
return [stu1.name compare:stu2.name];
}];
NSLog(@"%@", sortedArray);
}
2 sortedArrayUsingFunction
假如需要根据每个学生的英语成绩来进行排序,可以自定义排序的函数,然后通过sortedArrayUsingFunction方法来调用函数:
NSInteger sortStudentByCourseWithEnglish(id obj1, id obj2, void *context) {
Student *stu1 = (Student *)obj1;
Student *stu2 = (Student *)obj2;
if (stu1.course.englishRecords > stu2.course.englishRecords) {
return NSOrderedDescending;
} else if (stu1.course.englishRecords < stu2.course.englishRecords) {
return NSOrderedAscending;
}
return NSOrderedSame;
}
测试方法:
// 为对象自定义排序方法,采用sortedArrayUsingFunction进行排序
void sortedStudentByFunction() {
Course *cour1 = [Course courseWithEnglish:80.5 chinese:90];
Course *cour2 = [Course courseWithEnglish:78 chinese:78];
Course *cour3 = [Course courseWithEnglish:79.5 chinese:77];
// 为每个学生初始化课程分数
Student *stu1 = [Student studentWithName:@"Police" course:cour1];
Student *stu2 = [Student studentWithName:@"Tom" course:cour2];
Student *stu3 = [Student studentWithName:@"Alice" course:cour3];
// 初始化学生数组
NSArray *studentArray = [NSArray arrayWithObjects:stu1, stu2, stu3, nil];
// 调用自定义的排序方法
NSArray *sortedFunction = [studentArray sortedArrayUsingFunction:sortStudentByCourseWithEnglish
context:nil];
}
3 sortedArrayUsingSelector
sortedArrayUsingSelector方法与sortedArrayUsingFunciont类似,可以通过该方法调用OC对象中的方法。下面为Student类添加自定义的姓名排序方法:
// Student.h
/** 根据名字进行排序*/
- (NSComparisonResult)compareWithName:(Student *)student;
// Student.m
#pragma mark 实现Student根据名字的排序方法
- (NSComparisonResult)compareWithName:(Student *)student{
return [self.name compare:student.name];
}
测试方法:
NSArray *sortedStudentArray = [studentArray sortedArrayUsingSelector:@selector(compareWithName:)];
4 sortedArrayUsingDescriptor
最后是sortedArrayUsingDescriptor方法,这个可以算是NSArray里面的高级排序方法。以学生数组为例,假如需要分别根据英语成绩、汉语成绩和姓名进行升序排序,那么就可以采用这个方法。
// 采用NSSortDescriptor排序数组
void sortedStudentByNSSortDescriptor() {
// 课程分数
Course *course1 = [Course courseWithEnglish:87.5 chinese:88];
Course *course2 = [Course courseWithEnglish:90 chinese:77.5];
Course *course3 = [Course courseWithEnglish:80.5 chinese:78];
Course *course4 = [Course courseWithEnglish:60 chinese:91.5];
// 学生对象
Student *tom = [Student studentWithName:@"Tom Smith" course:course1];
Student *jim = [Student studentWithName:@"Oim Smith" course:course2];
Student *jerry = [Student studentWithName:@"Jerry Steven" course:course3];
Student *saly = [Student studentWithName:@"Saly Tomas" course:course4];
// 创建学生数组
NSArray *students = [NSArray arrayWithObjects:tom, jim, jerry, saly, nil];
// 排序策略:
// 1)sortDescriptorWithKey:@"course.englishRecords" 先根据学生的英语分数进行排序
// 2)sortDescriptorWithKey:@"course.chineseRecords" 再根据学生的汉语分数进行排序
// 3)sortDescriptorWithKey:@"name" 最后根据学生的姓名进行排序
// ascending:YES YES代表升序
NSSortDescriptor *englishDesc = [NSSortDescriptor sortDescriptorWithKey:@"course.englishRecords"
ascending:YES];
NSSortDescriptor *chineseDesc = [NSSortDescriptor sortDescriptorWithKey:@"course.chineseRecords"
ascending:YES];
NSSortDescriptor *nameDesc = [NSSortDescriptor sortDescriptorWithKey:@"name"
ascending:YES];
// 存放排序策略的数组
NSArray *descriptors = [NSArray arrayWithObjects:englishDesc, chineseDesc, nameDesc, nil];
// 进行排序
NSArray *sortedStudents = [students sortedArrayUsingDescriptors:descriptors];
}
备注
在NSMutableArray中,以上方法都可以使用,且可调用改变自身排序的方法,即没有返回新数组。罗列如下:
sortUsingComparator:^NSComparisonResult(id obj1, id obj2)cmpr
sortUsingFunction:(NSInteger (*)(id, id, void *)) context:(void *)
sortUsingSelector:(SEL)
sortUsingDescriptors:(NSArray *)