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阅读 221,548评论 6 515
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,497评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,990评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,618评论 1 296
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,618评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,246评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,819评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,725评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,268评论 1 320
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,356评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,488评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,181评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,862评论 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,331评论 0 24
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,445评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,897评论 3 376
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,500评论 2 359

推荐阅读更多精彩内容