- 簡單排序
- 利用block語法進(jìn)行排序
- 高級排序
- 拓展-分組問題
Objective-C對數(shù)據(jù)的操作可謂是非常用心,早已經(jīng)封裝好了很多方法等著我們?nèi)ネ诰?。其中對排序就是其中之一。本文是基于前人的基礎(chǔ)上進(jìn)行完善和加上自己的一些見解。
//NSComparisonResult類型結(jié)果
typedef NS_ENUM(NSInteger, NSComparisonResult) {
NSOrderedAscending = -1L,
NSOrderedSame,
NSOrderedDescending
};
簡單排序
sortedArrayUsingSelector:
通過指定方法對數(shù)組元素進(jìn)行排序。有一點(diǎn)需要記住,就是不管你自定義的方法是什么,都必須最后返回一個(gè)NSComparisonResult類型用于決定元素的排列原則。一般用于對字符串?dāng)?shù)組進(jìn)行排序,因?yàn)樽址凶詭У膶Ρ确椒?code>compare:。如果想對其他類型元素的數(shù)組進(jìn)行排序就需要我們自己自定義排序方法。
例如:
NSArray *array = @[@"abc",@"456",@"123",@"789",@"ef"];
NSArray *sortedArray = [array sortedArrayUsingSelector:@selector(compare:)];
NSLog(@"排序后:%@",sortedArray);
利用block語法進(jìn)行排序
sortedArrayUsingComparator:
假如我們有一個(gè)存儲了NSDate類型的數(shù)組需要進(jìn)行排序,那么我們可以通過compare:方法進(jìn)行排序。或者如果想自定義排序原則也可以使用如下方式:
NSArray *sortedArray = [array sortedArrayUsingComparator:^NSComparisonResult(NSDate *obj1, NSDate *obj2) {
if ([date1 timeIntervalSinceDate:date2] < 0) {
return NSOrderedDescending;
}
if ([date1 timeIntervalSinceDate:date2] > 0) {
return NSOrderedAscending;
}
return NSOrderedSame;
//或者使用compare:進(jìn)行排序
// NSComparisonResult result = [date1 compare:date2];
// return result;
}];
NSLog(@"排序后:%@",sortedArray);
假如我們有一個(gè)存儲了NSDate類型的數(shù)組需要進(jìn)行排序,那么我們可以通過此方法進(jìn)行排序。
NSArray *sortedArray = [array sortedArrayUsingComparator:^NSComparisonResult(NSDate * date1, NSDate * date2) {
if ([date1 timeIntervalSinceDate:date2] < 0) {
return NSOrderedDescending;
}
if ([date1 timeIntervalSinceDate:date2] > 0) {
return NSOrderedAscending;
}
return NSOrderedSame;
}];
NSLog(@"排序后:%@",sortedArray);
高級排序
sortedArrayUsingDescriptors: & sortUsingDescriptors:
前者帶返回值,是NSArray的方法,返回值中的數(shù)組是排好序的數(shù)組
后者不帶返回值,是NSMutableArray的方法,是對當(dāng)前數(shù)組自己排序
該方法是根據(jù)用戶的描述器(Descriptor)進(jìn)行排序。可能這樣說有點(diǎn)抽象,我們直接上代碼解釋:
假設(shè)我們有Person類,Car類。需要對Person進(jìn)行特定條件的排序,排序的原則就是優(yōu)先根據(jù)姓名排序,用戶名相同時(shí),再根據(jù)年齡排序,年齡也相同時(shí),再按照車進(jìn)行排序。
Car類
Car.h文件
@interface Car : NSObject
@property (nonatomic, copy) NSString *name;
+ (Car *)initWithName:(NSString *)name;
@end
Car.m文件
#import "Car.h"
@implementation Car
+ (Car *)initWithName:(NSString *)name {
Car *car = [Car alloc] init];
car.name = name;
return car;
}
@end
Person類
Person.h文件
@interface Person : NSObject
@property (nonatomic, copy ) NSString *name;
@property (nonatomic, assign) NSInteger age;
@property (nonatomic, strong) Car *car;
+ (Person *)personWithAge:(int)age withName:(NSString *)name withCar:(Car *)car;
@end
Person.m文件
#import "Person.h"
#import "Car.h"
@implementation Person
+ (Person *)personWithAge:(int)age withName:(NSString *)name withCar:(Car *)car {
Person *person = [[Person alloc] init];
person.age = age;
person.name = name;
person.car = car;
return person;
}
排序方法的實(shí)現(xiàn)
//首先來3輛車,分別是奧迪、勞斯萊斯、寶馬
Car *car1 = [Car initWithName:@"Audio"];
Car *car2 = [Car initWithName:@"Rolls-Royce"];
Car *car3 = [Car initWithName:@"BMW"];
//再來5個(gè)Person,每人送輛車,分別為car2、car1、car1、car3、car2
Person *p1 = [Person personWithAge:20 withName:@"Danny" withCar:car2];
Person *p2 = [Person personWithAge:21 withName:@"Kevin" withCar:car1];
Person *p3 = [Person personWithAge:24 withName:@"Maggie" withCar:car1];
Person *p4 = [Person personWithAge:23 withName:@"Danny" withCar:car3];
Person *p5 = [Person personWithAge:23 withName:@"LvChanghui" withCar:car2];
//加入數(shù)組
NSArray *array = @[p1,p2,p3,p4,p5];
//構(gòu)建排序描述器,這里很類似KVO的讀取屬性的方法,直接從字符串讀取對象屬性,注意不要寫錯(cuò)
NSSortDescriptor *carNameDesc = [NSSortDescriptor sortDescriptorWithKey:@"car.name"
ascending:YES];
NSSortDescriptor *personNameDesc = [NSSortDescriptor sortDescriptorWithKey:@"name"
ascending:YES];
NSSortDescriptor *personAgeDesc = [NSSortDescriptor sortDescriptorWithKey:@"age"
ascending:YES];
//把排序描述器放進(jìn)數(shù)組里,放入的順序就是你想要排序的順序
//這里是:首先按照姓名,然后是年齡排序,最后是按照車的名字
NSArray *descriptorArray = @[personNameDesc,personAgeDesc,carNameDesc];
NSArray *sortedArray = [array sortedArrayUsingDescriptors: descriptorArray];
NSLog(@"%@",sortedArray);
//如果是可變數(shù)組,則使用sortUsingDescriptors:
NSMutableArray *mutableArray = [NSMutableArray arrayWithArray:@[p1,p2,p3,p4,p5]];
[mutableArray sortUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
//此時(shí)mutableArray已經(jīng)排好順序
NSLog(@"%@",mutableArray);
拓展-分組問題
假如我們需要對字典(或?qū)ο?數(shù)組里面,根據(jù)字典(或?qū)ο螅?/code>元素的某個(gè)鍵值(或?qū)傩裕?/code>進(jìn)行分組。分組的思路無非就是將某個(gè)鍵值(或?qū)傩裕?/code>相同的字典(或?qū)ο螅?/code>放在一起。那么如何做到快速分組呢?這里就要引入一個(gè)新的類型NSMutableSet、NSSet
該類型具有無序的,不重復(fù)的特性(保證數(shù)據(jù)的唯一性)。當(dāng)插入相同的數(shù)據(jù)時(shí),不會有任何效果。從內(nèi)部實(shí)現(xiàn)來說是hash表。
例如:有一個(gè)Model類,需要根據(jù)Model里面的exchangeShortTime字段進(jìn)行分組
Model類
@interface Model : NSObject
@property (nonatomic, copy) NSString *exchangeShortTime;
@end
分組的實(shí)現(xiàn)
- (void)groupAction:(NSMutableArray *)arr {
//arr里面存儲著多個(gè)model對象,現(xiàn)在我們根據(jù)model中的exchangeShortTime字段進(jìn)行分組
NSMutableSet *set = [NSMutableSet set];
//利用set不重復(fù)的特性,得到有多少組,根據(jù)model中的exchangeShortTime字段
[arr enumerateObjectsUsingBlock:^(Model * _Nonnull model, NSUInteger idx, BOOL * _Nonnull stop) {
[set addObject:model.exchangeShortTime];
}];
/*此時(shí),set里面已經(jīng)存儲了可以分為組數(shù)*/
//接下來需要用到NSPredicate語法進(jìn)行篩選
__block NSMutableArray *groupArr = [NSMutableArray array];
[set enumerateObjectsUsingBlock:^(NSString * _Nonnull exchangeShortTime, BOOL * _Nonnull stop) {
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"exchangeShortTime = %@", exchangeShortTime];
NSArray *tempArr = [NSArray arrayWithArray:[arr filteredArrayUsingPredicate:predicate]];
[groupArr addObject:tempArr];
}];
}
大功告成!排序分組就講到這里。如果后面還有更多相關(guān)知識點(diǎn)會補(bǔ)充上。
再一次感謝您花費(fèi)時(shí)間閱讀這篇文章!
微博: @Danny_呂昌輝
博客: SuperDanny