我正在学习Swift中的高阶函数(如.map .filter .reduce ...)和泛型类型。
这是我的功能:
func max<T: Comparable>(_ array: [T]) -> T {
var max = 0 as! T
for value in array {
if value > max { max = value }
}
return max
}
如何用高阶函数替换for循环以获得相同的结果?
我希望做这样的事情(或更好):
max = array.map { $0 > max ? $0 : max }
答案 0 :(得分:3)
减少!
return array.reduce(nil)
{
(max: T?, current: T) -> T? in
guard let max = max else { return current }
return max > current ? max : current
}
这将返回一个可选项,但考虑到你可能会传入一个空数组,这可能是明智的。
当然也有这个
https://developer.apple.com/documentation/swift/array/1688806-max
问题的含义是这是一次学习练习。因此,这是使用更高阶函数的解决方案的概括。请注意,Swft Strandard Library已经包含了执行此操作的函数。
extension Array
{
func pickOne(choose: (Element, Element) -> Element) -> Element?
{
return self.reduce(nil)
{
(bestSoFar: Element?, current: Element) -> Element? in
guard let bestSoFar = bestSoFar else { return current }
return choose(bestSoFar, current)
}
}
}
因此,max的功能现在定义如下:
array.pickOne { $0 > $1 ? $0 : $1 }
和min将是
array.pickOne { $0 < $1 ? $0 : $1 }
答案 1 :(得分:1)
对于Ints,你可以这样使用reduce
:
// Reduce with initial value the first value of the array if available,
// or 0 otherwise
let max = array.reduce(array.first ?? 0) { (max, newValue) -> T in
return newValue > max ? newValue : max
}
更新
你想要JeremyP的答案,正确处理所有Comparable!
答案 2 :(得分:1)
首先请注意您的&#34;初始值&#34;和被迫 投
var max = 0 as! T
有两个问题:
max(["a", "b"]
)。max([-2, -3])
应该是-2
而不是零。所以你最好选择第一个数组元素作为初始值 &#34;强制零&#34;。
这导致了下一个问题:如果阵列怎么办? 是空的?有两种有效的方法:你可以要求 使用非空数组调用函数(并且使用该文件 先决条件):
/// Compute the maximal element in an array.
///
/// - Returns: The maximal element.
///
/// - Note: The array must not be empty.
func max<T: Comparable>(_ array: [T]) -> T {
precondition(!array.isEmpty, "`max` called with empty array")
var max = array[0]
for value in array {
if value > max { max = value }
}
return max
}
或(在其他答案中也有建议)作出返回值 可选的:
/// Compute the maximal element in an array.
///
/// - Returns: `nil` if the array is empty, and the maximal element otherwise.
func max<T: Comparable>(_ array: [T]) -> T? {
guard var max = array.first else { return nil }
for value in array {
if value > max { max = value }
}
return max
}
这两种方法都可以使用reduce()
来实现。
第一个是
/// Compute the maximal element in an array.
///
/// - Returns: The maximal element.
///
/// - Note: The array must not be empty.
func max<T: Comparable>(_ array: [T]) -> T {
precondition(!array.isEmpty, "`max` called with empty array")
return array.reduce(array[0]) { $0 > $1 ? $0 : $1 }
}
和第二个
/// Compute the maximal element in an array.
///
/// - Returns: `nil` if the array is empty, and the maximal element otherwise.
func max<T: Comparable>(_ array: [T]) -> T? {
guard let first = array.first else { return nil }
return array.reduce(first) { $0 > $1 ? $0 : $1 }
}
使用flatMap()
方法可以进一步缩短这一点
Optional
:
/// Compute the maximal element in an array.
///
/// - Returns: `nil` if the array is empty, and the maximal element otherwise.
func max<T: Comparable>(_ array: [T]) -> T? {
return array.first.flatMap { array.reduce($0) { $0 > $1 ? $0 : $1 } }
}
最后,您可以使用现有的
func max<T : Comparable>(_ x: T, _ y: T) -> T
在所有上述例子中,代替文字闭包,例如
/// Compute the maximal element in an array.
///
/// - Returns: `nil` if the array is empty, and the maximal element otherwise.
func max<T: Comparable>(_ array: [T]) -> T? {
return array.first.flatMap { array.reduce($0, max) }
}