版本记录
版本号 | 时间 |
---|---|
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;
该方法的作用就是:返回由给定的排序描述符数组指定的接收数组的副本。
下面我们就看一下参数和返回值:
-
sortDescriptors
:NSSortDescriptor
对象的数组。 -
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
)
结论:结合代码看,很好理解。
后记
未完,待续~~~