Reduce机制属于对数据集合的功能性操作,源自于功能性语言(map-reduce,fold)。历史上,该功能允许将任何集合转变为一个统一的聚合值(例如,和、积、字符串连接等),通过遍历其所有元素并累积结果。它解决的基本问题是:在不使用手动循环的情况下,以简洁、可读和无缺陷的方式聚合数据。
在Swift中,reduce被定义为集合的方法:
func reduce<Result>(_ initialResult: Result, _ nextPartialResult: (Result, Element) throws -> Result) rethrows -> Result
这意味着您指定初始值,然后编写一个函数,该函数为每个元素和当前累加器返回新的聚合值。
示例代码:
let numbers = [1, 2, 3, 4] let sum = numbers.reduce(0) { $0 + $1 } // 10 let joined = numbers.reduce("") { $0 + String($1) } // "1234"
关键特点:
reduce在空集合上如何工作?
Reduce应用于集合中的每个元素。如果集合为空——返回初始值,不会有任何闭包调用。
示例代码:
let empty: [Int] = [] let sum = empty.reduce(100) { $0 + $1 } // 100
可以通过reduce更改初始集合吗?
不可以,reduce是纯函数,它不改变初始集合。所有的变化只发生在累加器上。
reduce和reduce(into:)之间有什么区别?
reduce(into:)在每次遍历时允许改变累加器,更有效地处理价值类型,其中创建新副本(copy-on-write)是昂贵的。
示例代码:
let nums = [1, 2, 3] let squares = nums.reduce(into: []) { (result: inout [Int], item) in result.append(item * item) } // squares == [1, 4, 9]
开发人员想要计算存储在products数组中的产品价格总和。使用了初始值为0.0的reduce,但闭包的设计使得在存在折扣时有时返回负值,导致不正确的结果和计算税款的问题。
优点:
缺点:
使用reduce(into:)根据id从实体数组创建缓存:
let objects: [Entity] = ... let cache = objects.reduce(into: [:]) { $0[$1.id] = $1 }
优点:
缺点: