按照NSArray內(nèi)部的某個(gè)對(duì)象排序

stackoverflow上關(guān)于Objective-C關(guān)注度比較高的問題系列
鏈接

按照NSArray內(nèi)部的某個(gè)對(duì)象排序

原文鏈接How do I sort an NSMutableArray with custom objects in it?

本文Github鏈接

關(guān)鍵詞

Sort
NSArray
NSSortDescriptor

我想實(shí)現(xiàn)的事情看起來很簡單,但在網(wǎng)上卻找不到答案。有一個(gè)NSMutableArray or NSArray數(shù)組,數(shù)組中的元素是Person對(duì)象。我想按照Person.birthDate來排序,birthDate的類型是NSDate。

我猜測實(shí)現(xiàn)的方式的偽代碼應(yīng)該如下:

NSArray *sortedArray = [drinkDetails sortedArrayUsingSelector:@selecrot(???)];

排序方法

1) 對(duì)象中實(shí)現(xiàn)Compare方法(Compare method)

首先,在Person的implementation中實(shí)現(xiàn) compare method:

- (NSComparisonResult)compare:(Person *)person {
    return [self.birthDate compare:person.birthDate];
}

然后在需要排序的地方調(diào)用- (NSArray<ObjectType> *)sortedArrayUsingSelector:(SEL)comparator

NSArray *sortedArray = [array sortedArrayUsingSelector:@selector(compare:)];

2)NSSortDescriptor

NSSortDescriptorkey屬性為需要排序?qū)ο蟮哪硞€(gè)屬性(此處用到了KVC);ascending用于指定升序還是降序,YES-> 生序,NO->降序 ``

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"birthDate" ascending:YES];
NSSortDescriptor *nameSortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
    
NSArray *sortDescriptors = @[sortDescriptor,nameSortDescriptor];
NSArray *sortedArray = [array sortedArrayUsingDescriptors:sortDescriptors];

通過向array增加不同的key,可以很輕松的實(shí)現(xiàn)多個(gè)key復(fù)合排序(此處的復(fù)合排序指:當(dāng)?shù)谝粋€(gè)標(biāo)準(zhǔn)的兩個(gè)值相同時(shí),此時(shí)需要第二個(gè)標(biāo)準(zhǔn)來參與排序,第二個(gè)標(biāo)準(zhǔn)也相同的話就需要引入第三個(gè)標(biāo)準(zhǔn),以此類推)。

優(yōu)先比較sortDescriptors的第一項(xiàng),然后第二項(xiàng),然后第三項(xiàng),以此類推。

關(guān)于NSSortDescriptor可參考文件

3) Blocks

Mac OS X 10.6 和 iOS4之后也可以使用block來排序:

NSComparator sortComparator = ^NSComparisonResult(id a, id b) {
    NSDate *first = [(Person *)a birthDate];
    NSDate *second = [(Person *)b birthDate];
    return [first compare:second];
};
NSArray *sortedArray = [array sortedArrayUsingComparator:sortComparator];

一般來說,基于block和-compare:的方法實(shí)現(xiàn)起來會(huì)比使用NSSortDescriptor稍微快一點(diǎn),后者是依賴于KVCNSSortDescriptor的主要優(yōu)勢在于它可以直接使用數(shù)據(jù)來定義排序的標(biāo)準(zhǔn)即可,不需要自己來寫排序。在上一個(gè)例子中,只需要指定key是否為升序兩個(gè)參數(shù)就可以排序了,block方法還需要自己來compare first and second。

當(dāng)然在compare firstsecond的時(shí)候再復(fù)雜一些,比較一下Person的其他屬性也能達(dá)到NSSortDescriptor的復(fù)合排序。

結(jié)果及分析

我將以上三種方法各運(yùn)行一次得到的三次結(jié)果如下:

1)對(duì)象中實(shí)現(xiàn)Compare方法(Compare method)

original array:

name:       birthDate:          age:
 
Jixin       1526984251.000000    14 
Alex        1526923252.000000    22 
alex        1527983288.000000    21 
Chandler    1527983288.000000    23 
Kobe        1526083230.000000    24 
1Day        1426983253.000000    7 

-----------------------

1. 對(duì)象中實(shí)現(xiàn)Compare方法:

sorted array:
name:       birthDate:          age:
 
1Day        1426983253.000000    7 
Kobe        1526083230.000000    24 
Alex        1526923252.000000    22 
Jixin       1526984251.000000    14 
alex        1527983288.000000    21 
Chandler    1527983288.000000    23 

-----------------------
duration = 0.000061

Program ended with exit code: 0

分析結(jié)果

  1. 最終數(shù)組的順序是按照birthDate的由小到大排序;
  2. 最后兩個(gè)數(shù)據(jù)的birthDate相同卻沒有按照name的升序排列;
  3. 代碼執(zhí)行時(shí)間duration = 0.000061。

注:在ASCII碼中小寫字母是排在大寫字母后面的。字母a對(duì)應(yīng)的十進(jìn)制數(shù)是97,字母A對(duì)應(yīng)的十進(jìn)制數(shù)是65,字母C(此處C大寫)對(duì)應(yīng)的十進(jìn)制數(shù)是67)。

2)NSSortDescriptor

original array:

name:       birthDate:          age:
 
Jixin       1526984251.000000    25 
Alex        1526923252.000000    1 
alex        1527983288.000000    12 
Chandler    1527983288.000000    21 
Kobe        1526083230.000000    6 
1Day        1426983253.000000    4 

-----------------------

2. NSSortDescriptor方法:

sorted array:
name:       birthDate:          age:
 
1Day        1426983253.000000    4 
Kobe        1526083230.000000    6 
Alex        1526923252.000000    1 
Jixin       1526984251.000000    25 
Chandler    1527983288.000000    21 
alex        1527983288.000000    12 

-----------------------
duration = 0.000341

Program ended with exit code: 0

分析結(jié)果

  1. 最終數(shù)組的順序是按照birthDate的由小到大排序;
  2. 最后兩個(gè)數(shù)據(jù)的birthDate相同,然后按照name的升序排列。
  3. 代碼執(zhí)行時(shí)間duration = 0.000341。

3)Blocks

original array:

name:       birthDate:           age:
 
Jixin       1526984251.000000    21 
Alex        1526923252.000000    23 
alex        1527983288.000000    12 
Chandler    1527983288.000000    3 
Kobe        1526083230.000000    27 
1Day        1426983253.000000    12 

-----------------------

3. Block方法:
 
sorted array:
name:       birthDate:          age:
 
1Day        1426983253.000000    12 
Kobe        1526083230.000000    27 
Alex        1526923252.000000    23 
Jixin       1526984251.000000    21 
alex        1527983288.000000    12 
Chandler    1527983288.000000    3 

-----------------------
duration = 0.000062

Program ended with exit code: 0

分析結(jié)果

  1. 最終數(shù)組的順序是按照birthDate的由小到大排序;
  2. 最后兩個(gè)數(shù)據(jù)的birthDate相同卻沒有按照name的升序排列;
  3. 代碼執(zhí)行時(shí)間duration = 0.000062。

4)性能分析

在計(jì)算duration的時(shí)候,不同電腦,得到的結(jié)果是不一樣的,但是數(shù)字對(duì)應(yīng)的數(shù)量級(jí)應(yīng)該是一致的。

三次的時(shí)間分別如下:

  1. duration = 0.000061
  2. duration = 0.000341
  3. duration = 0.000062

可以看出前方法1和3的在同一個(gè)數(shù)量級(jí)上,第二種方法明顯其他兩種大一個(gè)數(shù)量級(jí)。

我們利用for循環(huán)將每部分代碼運(yùn)行1,000,000次,得到的結(jié)果如下:

  1. duration = 1.128369
  2. duration = 3.287778
  3. duration = 1.433518

依然可以得到相同的結(jié)果。1秒和3秒之間的差距,感知是很明顯的。

5)結(jié)論

  1. 如果沒有復(fù)合排序,可優(yōu)先選擇block方法。代碼較為集中看起來邏輯較清晰;
  2. 如果有復(fù)合排序,數(shù)據(jù)量不大的時(shí)候可以使用NSSortDescriptor;數(shù)據(jù)量較大時(shí)建議選擇block方法。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 有時(shí)候后臺(tái)返回的數(shù)組是沒有排序的,所以需要我們自己排序。有時(shí)候數(shù)組里面是一個(gè)字符串,但是有時(shí)候數(shù)組里面是自定義的類...
    人魔七七閱讀 3,457評(píng)論 1 6
  • 排序規(guī)則描述類: NSSortDescriptor NSSortDescriptor來指定排序規(guī)則, 對(duì)集合等進(jìn)行...
    SkyMing一C閱讀 6,720評(píng)論 3 12
  • 數(shù)組可對(duì)其中包含的元素進(jìn)行排序。 在排序前,我們需要定義一個(gè)Model類,將Model類對(duì)象添加至數(shù)組中。 定義一...
    SkyMing一C閱讀 11,073評(píng)論 0 15
  • 立冬前天氣,漸漸涼了,有一條帶絨的圍巾,卻怎么也找不到,翻騰來翻騰去,卻找出了你的花手帕。 那一刻,我呆住了,...
    花雨鳳飛H閱讀 424評(píng)論 8 4
  • 目錄 上一章 “顧雨,后天就是中考啦。復(fù)習(xí)得怎么樣了?”大宇笑著問。 “復(fù)習(xí)個(gè)屁啊,我可是考神的忠實(shí)擁躉,考神會(huì)保...
    唧唧王閱讀 173評(píng)論 0 1

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