NSArray簡單細說(八)—— 數組的排序

版本記錄

版本號 時間
V1.0 2017.08.25

前言

NSArray是集合類型中的一種,是OC中很重要的概念,這個是我們一定會用到的對象,下面我就繼續由整體到細節,由簡單到復雜的和大家說一下它的用法。感興趣的可以看我寫的上篇幾篇。
1. NSArray簡單細說(一)—— 整體了解
2. NSArray簡單細說(二)—— 數組的創建
3. NSArray簡單細說(三)—— 數組初始化
4. NSArray簡單細說(四)—— 數組的查詢與檢索
5. NSArray簡單細說(五)—— 數組中對象的查找
6. NSArray簡單細說(六)—— 向數組中元素發送消息
7. NSArray簡單細說(七)—— 數組的比較和獲得新數組

一、@property(readonly, copy) NSData *sortedArrayHint;

該屬性的作用就是:分析數組,并返回一個hint,當hint參數傳遞給sortedArrayUsingFunction: context:hint :時,可以加快數組的排序,上面調用的就是這個函數。

- (NSArray<ObjectType> *)sortedArrayUsingFunction:(NSInteger (*)(ObjectType, ObjectType, void *))comparator context:(void *)context hint:(NSData *)hint;

上面這個方法如何使用這里就不多說了,后面會和大家細說,下面我們看一下代碼。

- (void)demoSortedArrayHint
{
    NSArray *arr = @[@1, @2, @3];
    NSData *data = [arr sortedArrayHint];
    NSLog(@"%@", data);
}

下面看輸出結果

2017-08-25 21:13:01.514 JJOC[6905:176200] <b179379e 62f36e3c 136da6da>

這個大家是看不懂的,都是十六進制數據,后面會詳細的和大家說的。

結論:不怎么用,但是還是要了解下。


二、- (NSArray<ObjectType> )sortedArrayUsingFunction:(NSInteger ()(ObjectType, ObjectType, void *))comparator context:(void *)context;

該方法的作用就是:返回一個新的數組,該數組是按照比較函數比較器定義的升序排列的。

還有一點需要注意:

  • 新數組包含對接收數組元素的引用,而不是它們的副本。比較函數用于一次比較兩個元素,如果第一個元素小于第二個元素,則返回NSOrderedAscending,如果第一個元素大于第二個元素則返回NSOrderedDescending,如果元素相等則返回NSOrderedSame。 每次調用比較函數時,它將上下文作為第三個參數傳遞。 這允許比較基于一些外部參數,例如字符排序是區分大小寫還是不區分大小寫。

  • 給定一個Array(一個NSNumber對象的數組)和一個這種類型的比較函數,下面看代碼

NSInteger intSort(id num1, id num2, void *context)
{
    int v1 = [num1 intValue];
    int v2 = [num2 intValue];
    if (v1 < v2)
        return NSOrderedAscending;
    else if (v1 > v2)
        return NSOrderedDescending;
    else
        return NSOrderedSame;
}

以這種方式創建Array的排序:

NSArray *sortedArray; 
sortedArray = [anArray sortedArrayUsingFunction:intSort context:NULL];

結論:還算好理解。


三、- (NSArray<ObjectType> )sortedArrayUsingFunction:(NSInteger ()(ObjectType, ObjectType, void *))comparator context:(void *)context hint:(NSData *)hint;

該方法的作用就是:返回一個新數組,按照比較函數比較器定義的升序列出接收數組的元素。

還有幾點需要注意:

  • 新數組包含對接收數組元素的引用,而不是它們的副本。此方法類似于sortedArrayUsingFunction:context:,除了它使用提供的提示來加快排序過程。 當你知道數組幾乎被排序時,這個方法比sortedArrayUsingFunction:context:更快。 如果您排序了一個大數組(N個條目)一次,并且不會更改它(P的添加和刪除,P小于N),那么您可以通過概念上的方式重用您在原始排序中所做的工作 N個“舊”項目和P“新”項目之間的合并排序。
  • 要獲得適當的提示,請使用sortedArrayHint。 當原始數組被排序后,您應該獲取此提示,并在數組修改后保持該提示,直到需要它。 提示由O(N)中的sortedArrayHint計算(其中N是項目數)。 這假設數組中的項目實現了-hash方法。 給定一個合適的提示,并假設散列函數是一個“好”散列函數,-sortedArrayUsingFunction:context:hint:O(P * LOG(P)+ N)中對數組進行排序,其中P是添加或刪除的數量。 當P較小時,這是一個非暗示類型O(N * LOG(N))的改進。
  • 提示只是一個包含N個哈希值的大小為N的數組。 要重新排序,您需要在內部創建映射表,將散列映射到索引。 在新數組中使用此映射表,您可以首先猜出索引,然后進行排序。 例如,具有相應散列值{25,96,78,32,17}的排序數組{A,B,D,E,F}可能經受小的變化,導致內容{E,A,C, B,F}。 映射表將散列{25,96,78,32,17}映射到索引{#0,#1,#2,#3,#4}。 如果{E,A,C,B,F}的散列是{32,25,99,96,17},那么通過使用映射表,您可以得到第一個排序{#3,#0,?, #1,#4},因此創建一個初始半排序數組{A,B,E,F},然后用{ C }執行便宜的合并排序,得到{A,B,C,E,F}

結論:這個確實需要好好的理解一下,有點設計算法的底層了。


四、- (NSArray<ObjectType> *)sortedArrayUsingDescriptors:(NSArray<NSSortDescriptor *> *)sortDescriptors;

該方法的作用就是:返回由給定的排序描述符數組指定的接收數組的副本。

下面我們就看一下參數和返回值:

  • sortDescriptorsNSSortDescriptor對象的數組。
  • return:按sortDescriptors指定排序的接收數組的副本。

還有幾點需要注意:

  • 第一個描述符指定在對接收數組的內容進行排序時使用的主鍵路徑。 任何后續描述符用于進一步改進具有重復值的對象的排序。 有關其他信息,請參閱NSSortDescriptor

下面我們看一下代碼

- (void)demoSortedArrayUsingDescriptors
{
    NSDictionary *dic1 = [NSDictionary dictionaryWithObjectsAndKeys:@"2030",@"year", @"1",@"month",nil];
    NSDictionary *dic2 = [NSDictionary dictionaryWithObjectsAndKeys:@"2010",@"year", @"2",@"month", nil];
    NSDictionary *dic3 = [NSDictionary dictionaryWithObjectsAndKeys:@"2050",@"year", @"3",@"month" ,nil];
    NSDictionary *dic4 = [NSDictionary dictionaryWithObjectsAndKeys:@"2014",@"year",  @"4",@"month",nil];
    NSDictionary *dic5 = [NSDictionary dictionaryWithObjectsAndKeys:@"2050",@"year",  @"4",@"month",nil];
    
    NSArray *array = [NSArray arrayWithObjects:dic1, dic2, dic3, dic4, dic5, nil];
    
    NSSortDescriptor *descripor = [NSSortDescriptor sortDescriptorWithKey:@"year" ascending:NO];
    NSSortDescriptor *descripor2 = [NSSortDescriptor sortDescriptorWithKey:@"month" ascending:NO];
    NSArray *resultArr = [array sortedArrayUsingDescriptors:[NSArray arrayWithObjects:descripor, descripor2, nil]];
    
    NSLog(@"resultArr = %@", resultArr);
}

下面我們看一下輸出結果

2017-08-25 22:35:36.342 JJOC[8148:226465] resultArr = (
        {
        month = 4;
        year = 2050;
    },
        {
        month = 3;
        year = 2050;
    },
        {
        month = 1;
        year = 2030;
    },
        {
        month = 4;
        year = 2014;
    },
        {
        month = 2;
        year = 2010;
    }
)

結論:這個還是經常會用到的,大家需要好好看看。


五、- (NSArray<ObjectType> *)sortedArrayUsingSelector:(SEL)comparator;

該方法的作用是:返回一個數組,按照由給定選擇器指定的比較方法確定的升序列出接收數組的元素。

下面看一下參數和返回值:

  • comparator:標識用于一次比較兩個元素的方法的選擇器。 如果接收數組小于參數,則該方法應返回NSOrderedAscending,如果接收數組大于參數,NSOrderedDescending,如果相等則為NSOrderedSame
  • return:一個數組,由選擇器比較器指定的比較方法確定,按照升序排列接收數組的元素。

還有幾點需要注意:

  • 新數組包含對接收數組元素的引用,而不是它們的副本。
    比較器消息被發送到數組中的每個對象,并且在數組中具有另一個對象。例如,NSString對象的數組可以使用在NSString類中聲明的caseInsensitiveCompare:方法進行排序。 假設存在anArray,則可以按以下方式創建數組的排序方式:
 NSArray *sortedArray = [anArray sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];

下面看完整代碼

- (void)demoSortedArrayUsingSelector
{
    NSArray *arr = @[@"hello", @"how", @"are", @"you"];
    NSArray *resultArr = [arr sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
    NSLog(@"resultArr = %@", resultArr);
}

下面看輸出結果

2017-08-25 22:59:07.430 JJOC[8986:249270] resultArr = (
    are,
    hello,
    how,
    you
)

結論:這個方法還是挺有意思的。


六、- (NSArray<ObjectType> *)sortedArrayUsingComparator:(NSComparator)cmptr;

該方法的作用就是:返回一個數組,按照由給定的NSComparator塊指定的比較方法確定的升序列出接收數組的元素。

對于返回值,就是一個數組,按照指定的cmptr的比較方法,按升序列出接收數組的元素。

下面我們就看一下代碼

- (void)demoSortedArrayUsingComparator
{
    NSArray *arr = @[@"hello", @"how", @"are", @"you"];
    NSArray *resultArr = [arr sortedArrayUsingComparator:^NSComparisonResult(id  _Nonnull obj1, id  _Nonnull obj2) {
         return [obj1 compare:obj2];
    }];
    NSLog(@"resultArr = %@", resultArr);
}

下面看輸出結果

2017-08-25 23:10:48.071 JJOC[9363:257667] resultArr = (
    are,
    hello,
    how,
    you
)

上面這個就是按照升序進行排列的,那么按照降序呢,可以進行如下修改:

[obj2 compare:obj1];

下面看輸出結果

2017-08-25 23:12:02.545 JJOC[9490:259440] resultArr = (
    you,
    how,
    hello,
    are
)

結論:這個總會用到,好好理解下就可以了,不難的。


七、- (NSArray<ObjectType> *)sortedArrayWithOptions:(NSSortOptions)opts usingComparator:(NSComparator)cmptr;

該方法的作用就是:返回一個數組,按照由給定的NSComparator塊指定的比較方法確定的升序列出接收數組的元素。

下面我們看一下參數和返回值:

  • opts:指定排序選項的位掩碼(是否應同時執行以及是否應穩定執行)。這里是一個枚舉,如下所示。
typedef NS_OPTIONS(NSUInteger, NSSortOptions) {
    NSSortConcurrent = (1UL << 0),
    NSSortStable = (1UL << 4),
};
  • cmptr:比較器的代碼塊。
  • return:一個數組,按照指定的cmptr的比較方法,按升序列出接收數組的元素。

下面我們看代碼

- (void)demoSortedArrayWithOptions
{
    NSArray *arr = @[@"6", @"9", @"2", @"1"];
    NSArray *resultArr = [arr sortedArrayWithOptions:NSSortConcurrent usingComparator:^NSComparisonResult(id  _Nonnull obj1, id  _Nonnull obj2) {
        return [obj1 compare:obj2];
    }];
    NSLog(@"resultArr = %@", resultArr);
}

下面看輸出結果

2017-08-25 23:20:22.843 JJOC[9834:267493] resultArr = (
    1,
    2,
    6,
    9
)

結論:結合代碼看,很好理解。

后記

未完,待續~~~

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,836評論 6 540
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,275評論 3 428
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,904評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,633評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,368評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,736評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,740評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,919評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,481評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,235評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,427評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,968評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,656評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,055評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,348評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,160評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,380評論 2 379

推薦閱讀更多精彩內容