前语
Swift 的 Sequence
类型有一个强壮的操作符叫做 reduce
,它允许你将序列的一切元素组合成一个单一的值。在处理来自 App Store Connect API 的响应时,我一直在重复运用它,我觉得写一篇关于它的博客文章是个好主意。
reduce
操作符有两种不同的签名,具体代码如下:
// 运用初始成果进行 reduce
@inlinable public func reduce<Result>(_ initialResult: Result, _ nextPartialResult: (_ partialResult: Result, Self.Element) throws -> Result) rethrows -> Result
// 将成果归并到初始成果中
@inlinable public func reduce<Result>(into initialResult: Result, _ updateAccumulatingResult: (_ partialResult: inout Result, Self.Element) throws -> ()) rethrows -> Result
这两个操作符在给定相同输入时完成相同的成果:它们从一个初始的 inout
值开端,遍历序列中的一切元素,并将它们作为参数传递给供给的闭包。因为初始值是作为 inout
参数传递的,闭包能够依据序列中的当时元素对其进行修改。每次迭代的更新值然后作为下一次迭代中闭包的第一个参数传递。
虽然它们看起来十分类似 – 它们都具有 O(n) 的复杂度,并且能够互换运用 – 但基于成果类型的不同,它们具有不同的功率影响。例如,当成果是像 Array
或 Dictionary
这样的写时复制类型时,你应该运用 into
变体。
运用初始成果进行 reduce
让咱们来看一个十分简单的比如,以理解 reduce
操作符的作业原理。假定你有一个整数数组,你想要核算一切元素的总和作为成果。假如你不知道 reduce
操作符,你能够写一个像这样的函数,具体代码如下:
func sumAllElements(of numbers: [Int]) -> Int {
var sum = 0
for number in numbers {
sum += number
}
return sum
}
虽然这个函数彻底有用,但它并不是最优雅的解决方案。你能够在一行代码中运用 reduce
操作符来完成相同的成果,代码如下:
func sumAllElements(of numbers: [Int]) -> Int {
numbers.reduce(0) { $0 + $1 }
}
或者更好的是,你能够直接将 +
操作符作为闭包传递,代码如下:
func sumAllElements(of numbers: [Int]) -> Int {
numbers.reduce(0, +)
}
运用初始成果进行 reduce
现在让咱们来看一个稍微复杂一些的比如。假定咱们有一个 ScreenshotBundle
数组,其间每个 bundle
都有一个称号和一个指向截图的 URL
列表。咱们的 UI 需求依据用户的挑选找到具有特定称号的截图 bundle,并在图像视图中显现一切的 URL
:
这是咱们在 Helm 中运用的代码变体,Hidde 和我正在构建 Helm,这是一款旨在使 App Store Connect 的用户更轻松、更愉快地发布运用程序和更新的运用。
咱们能够经过坚持 ScreenshotBundle
数组不变,然后搜索具有特定称号的 bundle 来完成这一点,中心代码如下:
struct ScreenshotBundle {
let name: String
let urls: [URL]
}
func find(bundleWithName name: String, in bundles: [ScreenshotBundle]) -> ScreenshotBundle? {
bundles.first(where: { $0.name == name })
}
虽然这种方法可行,但它并不是最有用的。first(where:)
函数的复杂度为 O(n),你能够想象,假如数组中的元素数量很大,这可能会成为一个问题。
相反,你能够运用 reduce
操作符一次将 ScreenshotBundle
数组转换为一个字典,其间键是 bundle 的称号,值是 bundle 本身。这样,你就能够在 O(1) 的时刻复杂度内找到具有特定称号的 bundle,代码如下:
struct ScreenshotBundle {
let name: String
let urls: [URL]
}
func format(bundles: [ScreenshotBundle]) -> [String: ScreenshotBundle] {
bundles.reduce(into: [String: ScreenshotBundle]()) { result, bundle in
result[bundle.name] = bundle
}
}
func find(bundleWithName name: String, in bundles: [String: ScreenshotBundle]) -> ScreenshotBundle? {
bundles[name]
}
经过理解和把握 reduce 操作符,你能够更高效地处理 Swift 中的集合类型,使你的代码更加简洁和易于理解。这种强壮的操作符不仅能够提高代码的性能,还能提升开发功率,让你更轻松地应对复杂的数据处理任务。
在实际开发中,应该依据具体情况挑选适宜的 reduce 操作符,以确保代码的性能和可读性。经过合理地利用 reduce 操作符,你能够编写出更加优雅和高效的 Swift 代码,然后提升运用程序的质量和用户体会。
了解 reduce 操作符的作业原理并熟练运用它,将会使你成为一个更加出色的 Swift 开发者,为你的项目带来更大的成功和成就。
总结
本文全面介绍了 Swift 中的 reduce 操作符,这是一个强壮的东西,能够将序列的元素组合成单个值。文章解释了 reduce 操作符的两种不同签名,并经过代码示例演示了它们的用法。
其间评论了怎么运用带有初始成果的 reduce,演示了怎么以简洁而优雅的方式核算数组中元素的总和。然后,它探讨了带有初始成果的 reduce 变体,展现了怎么将数组高效地转换为字典。
本文对 Swift 开发人员来说是一份宝贵的资源,供给了关于 reduce 操作符的功能和运用的见地,使他们能够编写更高效、更优雅的代码。