按照NSArray內部的某個物件排序
stackoverflow上關於Objective-C關注度比較高的問題系列
連結
按照NSArray內部的某個物件排序
原文連結How do I sort an NSMutableArray with custom objects in it?
本文Github連結
關鍵詞
Sort
NSArray
NSSortDescriptor
我想實現的事情看起來很簡單,但在網上卻找不到答案。有一個NSMutableArray
or NSArray
陣列,陣列中的元素是Person
物件。我想按照Person.birthDate
來排序,birthDate
的型別是NSDate
。
我猜測實現的方式的虛擬碼應該如下:
NSArray *sortedArray = [drinkDetails sortedArrayUsingSelector:@selecrot(???)];
排序方法
1) 物件中實現Compare方法(Compare method)
首先,在Person的implementation中實現 compare
method:
- (NSComparisonResult)compare:(Person *)person {
return [self.birthDate compare:person.birthDate];
}
然後在需要排序的地方呼叫- (NSArray<ObjectType> *)sortedArrayUsingSelector:(SEL)comparator
。
NSArray *sortedArray = [array sortedArrayUsingSelector:@selector(compare:)];
2)NSSortDescriptor
NSSortDescriptor
的key
屬性為需要排序物件的某個屬性(此處用到了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,可以很輕鬆的實現多個key複合排序(此處的複合排序指:當第一個標準的兩個值相同時,此時需要第二個標準來參與排序,第二個標準也相同的話就需要引入第三個標準,以此類推)。
優先比較sortDescriptors的第一項,然後第二項,然後第三項,以此類推。
關於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:
的方法實現起來會比使用NSSortDescriptor
稍微快一點,後者是依賴於KVC
。NSSortDescriptor
的主要優勢在於它可以直接使用資料來定義排序的標準即可,不需要自己來寫排序。在上一個例子中,只需要指定key
和是否為升序
兩個引數就可以排序了,block方法還需要自己來compare first
and second
。
當然在compare first
和second
的時候再複雜一些,比較一下Person的其他屬性也能達到NSSortDescriptor的複合排序。
結果及分析
我將以上三種方法各執行一次得到的三次結果如下:
1)物件中實現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. 物件中實現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
分析結果
- 最終陣列的順序是按照
birthDate
的由小到大排序; - 最後兩個資料的
birthDate
相同卻沒有按照name
的升序排列; - 程式碼執行時間duration = 0.000061。
注:在ASCII碼中小寫字母是排在大寫字母后面的。字母a
對應的十進位制數是97,字母A
對應的十進位制數是65,字母C
(此處C大寫)對應的十進位制數是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
分析結果
- 最終陣列的順序是按照
birthDate
的由小到大排序; - 最後兩個資料的
birthDate
相同,然後按照name
的升序排列。 - 程式碼執行時間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
分析結果
- 最終陣列的順序是按照
birthDate
的由小到大排序; - 最後兩個資料的
birthDate
相同卻沒有按照name
的升序排列; - 程式碼執行時間duration = 0.000062。
4)效能分析
在計算duration的時候,不同電腦,得到的結果是不一樣的,但是數字對應的數量級應該是一致的。
三次的時間分別如下:
- duration = 0.000061
- duration = 0.000341
- duration = 0.000062
可以看出前方法1和3的在同一個數量級上,第二種方法明顯其他兩種大一個數量級。
我們利用for迴圈將每部分程式碼執行1,000,000次,得到的結果如下:
- duration = 1.128369
- duration = 3.287778
- duration = 1.433518
依然可以得到相同的結果。1秒和3秒之間的差距,感知是很明顯的。
5)結論
- 如果沒有複合排序,可優先選擇block方法。程式碼較為集中看起來邏輯較清晰;
- 如果有複合排序,資料量不大的時候可以使用NSSortDescriptor;資料量較大時建議選擇block方法。
相關文章
- 陣列物件按物件某個屬性排序陣列物件排序
- 「Js」物件按照鍵名來進行排序JS物件排序
- Js實現Object按照值的某個欄位(數值型別)的大小進行排序JSObject型別排序
- JAVA裡List集合中的物件根據物件的某個屬性值降序或者升序排序Java物件排序
- 按照價格排序!排序
- JavaScript內部物件和Date物件JavaScript物件
- mysql資料表按照某個欄位分類輸出MySql
- 讓 排序 按照 in 列表的的顯示順序排序輸出。排序
- Elasticsearch 按照標籤匹配個數優先排序查詢Elasticsearch排序
- 物件導向之內部類物件
- js 取陣列中某個物件的集合JS陣列物件
- Js陣列物件的屬性值升序排序,並指定陣列中的某個物件移動到陣列的最前面JS陣列物件排序
- 逆向工程通過某個欄位排序排序
- Python基礎之:Python中的內部物件Python物件
- 非k8s環境下,進入docker某個容器內部K8SDocker
- 寫個方法判斷陣列物件中是否存在某個物件陣列物件
- PHP 多維陣列排序-按某個 key 的值PHP陣列排序
- C#獲取某個物件的屬性值C#物件
- java8的stream將一個List轉為按照某個欄位分組的map,再按照另一個欄位取max最終得到一個mapJava
- thinkphp where in order 按照順序in的迴圈排序PHP排序
- 大模型內部有一個平面和直邊構成的幾何物件大模型物件
- JavaScript按照漢字拼音順序排序JavaScript排序
- 如何檢查某個使用者是否具有某個許可權物件上定義的某種許可權物件
- 論如何監聽物件某個屬性的變化物件
- Redis 物件內部組織結構 —— 字典Redis物件
- 物件導向--內部屬性型別物件型別
- 二維陣列根據某個欄位排序陣列排序
- List集合按照由小到大排序或者由大到小排序排序
- 判斷某個陣列在不在物件裡陣列物件
- 1636 按照頻率將陣列升序排序陣列排序
- Java之區域性匿名內部類物件Java物件
- 通過反射獲取私有內部類物件反射物件
- 按照陣列順序給物件重新組合成新物件陣列物件
- OC-NSArray的基本介紹
- 欄位按照指定 ID 順序進行排序排序
- 用 Java 實現常見的 8 種內部排序演算法Java排序演算法
- JAVA物件導向基礎--N種內部類Java物件
- js--物件內部屬性與 Object.defineProperty()JS物件Object