字典數(shù)組、對象數(shù)組排序以及分組


  • 簡單排序
  • 利用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è)新的類型NSMutableSetNSSet

該類型具有無序的,不重復(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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Objective-C對數(shù)據(jù)的操作可謂是非常用心,早已經(jīng)封裝好了很多方法等著我們?nèi)ネ诰?。其中對排序就是其中之一?...
    Xayoung_Coder閱讀 556評論 0 0
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,533評論 19 139
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,637評論 18 399
  • java筆記第一天 == 和 equals ==比較的比較的是兩個(gè)變量的值是否相等,對于引用型變量表示的是兩個(gè)變量...
    jmychou閱讀 1,644評論 0 3
  • 本文簡單介紹在iOS開發(fā)過程中經(jīng)常用到的四種數(shù)據(jù)存儲方式: 1.NSKeyedArchiver 2.NSUserD...
    March_Cullen閱讀 949評論 0 2

友情鏈接更多精彩內(nèi)容