OC中的NSArray提供了较多的排序方法,可以对数组元素进行有效的排序,下面先准备一个Student和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; }
// 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]; }
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); }
假如需要根据每个学生的英语成绩来进行排序,可以自定义排序的函数,然后通过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]; }
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:)];
最后是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 *)