在常用的高阶函数中,相比于 map、flatMap、filter 这些,reduce 理解起来更晦涩一些,不如前面几个功能明确。
reduce 一词,在英文中的解释为“减少、降低等”,在函数式编程中,我们可以把这个单词理解为“合并、归纳”。也就是说,reduce 的作用是合并结果,把多项变成一项。至于怎么合并,就看传入的转换方法是什么。
部分编程语言也会使用 fold、compress 等表示 reduce ,参考 https://en.wikipedia.org/wiki/Fold_%28higher-order_function%29 。但是主流编程语言中,还是使用 reduce 一词的比较多。
Swift中的 reduce
Swift提供了两个不同的 reduce 方法。
reduce(_:_:)
1 | /// Returns the result of combining the elements of the sequence using the given closure. |
reduce(into:_:)
1 | /// Returns the result of combining the elements of the sequence using the given closure. |
两个方法的作用完全一样,都是 Returns the result of combining the elements of the sequence using the given closure ,翻译过来就是 使用传入的closure合并序列并返回 。在使用上两个方法有什么区别呢?
TLDR: 具体作用没区别。只是当返回结果为
Array、Dictionary等 Coy On Write 类型的数据时,优先使用reduce(into:_:)以提升性能。
reduce(_:_:)
1 | /// - Parameters: |
以下面的代码为例,介绍reduce(_:_:)的执行流程。
1 | let numbers = [1, 2, 3, 4] |
- 调用 nextPartialResult,传入的参数为
x: *initialResult(0),y:*numbers 数组第一个元素(1),返回相加的结果:1。 - 继续调用 nextPartialResult,传入的参数为
x: 上一步的返回值,y:numbers 数组下一个元素,返回相加的结果。 - numbers 数组遍历完毕后,将最后的结果最为返回值返回。
如果 numbers 数组为空,则 nextPartialResult 不会执行,直接返回 initialResult。
reduce(into:_:)
1 | /// - Parameters: |
以下面的代码为例,介绍reduce(into:_:)的执行流程。
1 | let letters = "abracadabra" |
- 调用 updateAccumulatingResult,传入的参数为
counts: *initialResult([:]),letter: *letters 数组第一个元素(a),返回结果:[a: 1]。 - 继续调用 updateAccumulatingResult ,传入的参数为
counts: 上一步的返回值,letter: letters 数组下一个元素,返回结果。 - letters 数组遍历完毕后,将最后的结果最为返回值返回。
如果 letters 数组为空,则 updateAccumulatingResult 不会执行,直接返回 initialResult 。
总结
reduce(_:_:) 和 reduce(into:_:) 除了参数不一样外真没啥区别。不过从方法命名上看,我们也能大概猜到 reduce(into:_:) 会把归并结果会更新到 initialResult ,这应该就是Swift官方推荐当返回结果为Array、Dictionary等 Coy On Write 类型的数据时,优先使用reduce(into:_:)的原因。
This method(
reduce(into:_:)) is preferred overreduce(_:_:)for efficiency when the result is a copy-on-write type, for example an Array or a Dictionary.
使用reduce实现map、filter等
弄明白 reduce 的原理之后,大家可以发现这是一个很灵活的方法。基本上能用 map、filter 实现的功能都可以用 reduce 代替。
使用reduce实现map
1 | extension Array { |
使用reduce实现filter
1 | extension Array { |