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 {
    [_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 *)
时间: 2024-11-05 14:53:01

OC基础-NSArray排序的相关文章

OC基础(23)

NSArray基本概念 NSArray 遍历 NSArray排序 NSArray文件读写 NSArray 与字符串 *:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } a { color: #4183C4; } a.absent { color: #cc0000; } a.anchor { display: block; padding-left: 30p

OC基础第五讲--Block、数组高级、字面量

Block 1.1block与函数指针 函数: int sum(int x, int y) { retrun x + y; } 函数指针: 把上面函数原型int sum(int x, int y)中的函数名替换成(*p),即可得到一个函数指针int (*p)(int x, int y). 这个函数表示指针p指向一个函数,这个函数有两个int型参数,返回值是int类型. Block:把函数指针int (*p)(int x, int y)中的'*'换成'^'就是我们block的声明,即int (^p

oc基础知识(转)

1.项目经验 2.基础问题 3.指南认识 4.解决思路 ios开发三大块: 1.Oc基础 2.CocoaTouch框架 3.Xcode使用 -------------------- CocoaTouch Media Core Services Core OS -------------------- System Framework OC的类声明,定义域 OC关键字定义为  @class O-C特有的语句for(..in ..)迭代循环,其他的条件和循环语句和c一样 OC对面向对象的概述 (1)

黑马程序员--oc基础第十篇(foundation框架下、集合)

十 . oc基础(Foundation框架下) 1.下面介绍几种OC对象类型的存储结构:NSArray,NSDictionary,NSSet,以及基本数据类型封装类. NSNumber:*既然这几种数据结构都是用来存放对象类型的那么基本数据类型想要放入其中就要先对他们进行封装.使用NSNumber对基本数据类型进行封装. // // Created by keeganlee on 15/3/2. // Copyright (c) 2015年 keeganlee. All rights reser

OC基础01

搜索 "==>" 寻找标记 OC基础总结: Objective-C具有相当多的动态特征,如: " 动态类型 , 动态绑定 , 动态加载" ==> copy mutableCopy 浅复制: 在复制操作中,对于被复制的对象的每一层复制都是指针复制. 深复制: 在复制操作中,对于被复制的对象至少有一层是对象复制 完全复制: 在复制操作中,对于被复制的对象的每一层都是对象复制. 一般来讲: 浅复制复制引用对象的指针 深复制 复制引用对象的内容 retain &

OC基础 可变字典与不可变字典的使用

OC基础 可变字典与不可变字典的使用 1.不可变字典 1.1创建不可变字典 //创建字典 //注意: //1,元素个数是偶数 //2,每两个元素是一个键值对 //3,值在前,键在后 NSDictionary *dic = [[NSDictionary alloc] initWithObjectsAndKeys:@"huang",@"name",@"30",@"age", nil]; NSLog(@"%@",

OC基础(21)

Foundation框架介绍 NSString基本概念 字符串读写 字符串比较 字符串搜索 字符串截取 字符串替换 字符串与路径 字符串与基本数据类型转换 *:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } a { color: #4183C4; } a.absent { color: #cc0000; } a.anchor { display: bloc

OC基础 04

OC 基础04 [email protected]基本概念 >[email protected]是编译器的指令 >[email protected] 用在声明文件中告诉编译器声明成员变量的的访问器(getter/setter)方法 这样的好处是:免去我们手工书写getter和setter方法繁琐的代码 @property基本使用 1.在@inteface中,用来自动生成setter和getter的声明 示例: 用@property int age; // 就可以代替下面的两行 - (int)a

OC基础 内存管理

OC基础  内存管理 我们所了解的c语言内存管理,如下: (1)c语言的内存分配:char *p = (char*)malloc(100*sizeof(char)); (2)c语言的内存释放:free(p); c语言内存管理存在的缺陷: (1)不释放就会造成内存泄露. (2)多次释放就会造成崩溃. (3)大型项目中多人对一块内存进行操作时,不能释放内存,因为不知道别人是否还在使用. oc语言的内存管理 1.内存管理 (1)引用计数. (2)内存管理的黄金法则:谁创建谁释放. 让我们来看一下测试例

OC基础 文件管理

OC基础  文件管理 1.文件管理类NSFileManager对象的创建: NSFileManager *fm = [NSFileManager defaultManager]; 2.文件操作: (1)遍历查看目录下的文件: a.遍历查看目录下的文件:contentsOfDirectorAtPath:(NSString *)path error:(NSError **)error: b.深度遍历,子目录也遍历:subPathsOfDirectorAtPath:(NSString *)path e