OC基础-NSArray排序

    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 *)

你可能感兴趣的:(OC基础,NSArray排序)