「这是我参与2022首次更文挑战的第28天,活动详情查看: 2022首次更文挑战 」。
Swift
提供的如下几个高阶函数:
map
、
flatMap
、
compactMap
、
filter
、
reduce
。
1. map
Map 函数作用于
Collection
中的每一个元素,然后返回一个新的
Collection
。map函数获取一个闭包表达式成为它唯一的参数,之后数组中的每一个元素调用该闭包表达式,并返回该元素映射的值。
1.1 使用
数组转换
为String数组
我们可以直接对元素进行操作,也可以用
$0
表示每一个元素。
可以发现返回的是一个可选值元素的数组,包含无法转换的nil。
二维数组
生成一个新的Int数组,元素是多少元素就重复多少个
返回的是二维数组
1.2 源码分析
我们在
collection.swift
查看map的实现
主要是先构造一个和原数组个数一样的数组,之后便利原数组中的每一个元素,通过
transform
做相对应的操作,之后进行
append
到新数组,最后返回一个
新的数组
。
2. flatMap
2.1 使用
可以看到
flatMap
是把数组中的数组进行了压平的操作,相当于
二维数组转换为一维的数组
。
当然我们也可以对二维数组继续
map
操作,转换为
String
。
对于本身就是一维的话,
map和flatmap
效果一样。
2.2 源码分析
可以发现和map类似,先创建一个数组里面的元素类型是
SegmentOfResult.Element
。调用闭包的转换函数
transform
,进行转换;之后通过
append
添加每个数组的元素。
相比较我们的
map
来说,
flatMap
最主要的两个作用一个是
压平
,一个是
过滤空值
。
map
做集合操作之后,得到的
reslut
是一个可选的可选,那么这里 其实我们在使用
result
的过程中考虑的情况就比较多
通过
flatMap
我们就可以得到一个可选值而不是
可选的可选
看下源码:
flatMap
对于输入一个可选值时应用闭包返回一个可选值,之后这个结果会被压平, 也就是返回一个解包后的结果。本质上,相比
map
,
flatMap
也就是在可选值层做了一个
解包
。
使用
flatMap
就可以在链式调用时,不用做额外的解包工作
3. compactMap
当转换闭包返回可选值并且你期望得到的结果为非可选值的序列时,使用
compactMap
。
3.1 使用
会
自动过滤nil
3.2 源码分析
可以发现和之前的map类似的流程,从这里就可以得出结论,
compactMap
与
map
的区别就在于,
map
将
transform
后的结果直接放入
result
中,而
compactMap
使用
if-let
后再放入
result
中,而
if-let
的作用就是解包和过滤
nil
。
4. filter
filter是用来过滤的,类似我们oc中对数组使用
谓词
4.1 使用
返回的是所有大于2的元素数组
4.2 源码分析
使用迭代器,遍历所有的元素,对于每个元素,调用闭包
isIncluded
,判断是否符合条件。符合后加入到我们创建的数组中。
5. reduce
主要是用来对集合中每个元素和叠加器做对应操作
@inlinable public func reduce<Result>(_ initialResult: Result, _ nextPartialResult: (Result, Element) throws -> Result) rethrows -> Result
@inlinable public func reduce<Result>(into initialResult: __owned Result, _ updateAccumulatingResult: (inout Result, Element) throws -> ()) rethrows -> Result
这2个方法有些类似的,差别在于闭包的定义。
第一个函数闭包,接收Result和Element,返回闭包执行后的Result,后续的操作是将每次闭包执行后的Result当做下一个元素执行闭包的入参,遍历完所有元素;
第二个函数闭包,接收的也是Result和Element,没有返回值,并且Result是用inout修饰的,所以传入闭包的是Result的地址,所以闭包的执行都是基于Result进行操作的。
5.1 使用
找出数组中的最大值
把数组进行逆序
5.2 源码分析
对于第一种:
累加器记录每次的状态,其次通过迭代器便利传入每次的结果和元素,遍历完成后,返回 accumulator。
对于第二种:
和第一种的区别在于,没有每次便利的时候对accumulator赋值,直接取它的地址&accumulator
遍历所有的元素,对于每个元素,调用闭包 updateAccumulatingResult,参数是临时变量 accumulator 的地址,闭包执行其实就是更新 accumulator 的值;