高阶函数分配

时间:2017-07-12 09:40:38

标签: swift generics

我正在学习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 }

3 个答案:

答案 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) }
}