在Swift中找到数组中max的正确方法

Cha*_*gan 113 arrays swift

到目前为止,我有一种简单(但可能很昂贵)的方式:

var myMax = sort(myArray,>)[0]
Run Code Online (Sandbox Code Playgroud)

我是如何被教导在学校做的:

var myMax = 0
for i in 0..myArray.count {
    if (myArray[i] > myMax){myMax = myArray[i]}
}
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法从Swift中的整数数组中获取最大值?理想情况下,像Ruby这样的一行.max

Rud*_*vič 278

鉴于:

let numbers = [1, 2, 3, 4, 5]
Run Code Online (Sandbox Code Playgroud)

斯威夫特3:

numbers.min() // equals 1
numbers.max() // equals 5
Run Code Online (Sandbox Code Playgroud)

斯威夫特2:

numbers.minElement() // equals 1
numbers.maxElement() // equals 5
Run Code Online (Sandbox Code Playgroud)

  • 仅适用于`Comparable`对象,因此`NSDecimalNumber`不会起作用. (2认同)
  • 它只是我还是在Swift 2中不存在这些功能? (2认同)
  • 注意在Swift 3中,这些已经被重命名为`min()`和`max()`. (2认同)

Jea*_*let 91

更新: 应该是自maxElementSwift中出现以来接受的答案.


使用全能reduce:

let nums = [1, 6, 3, 9, 4, 6];
let numMax = nums.reduce(Int.min, { max($0, $1) })
Run Code Online (Sandbox Code Playgroud)

同理:

let numMin = nums.reduce(Int.max, { min($0, $1) })
Run Code Online (Sandbox Code Playgroud)

reduce取第一个值作为内部累加器变量的初始值,然后将传递的函数(这里,它是匿名的)连续地应用于累加器和数组的每个元素,并将新值存储在累加器中.然后返回最后一个累加器值.

  • @ Jean-PhilippePellet你实际上可以将它简化为:`nums.reduce(Int.min,max)`因为`max`的原型已经匹配`reduce`期待的类型 (10认同)
  • min/max函数签名与combine:参数签名匹配,因此您只需传递函数:`let numMax = nums.reduce(Int.min,combine:max)` (3认同)
  • 这些只是一般的函数式编程技术,它们不是特定于Swift的. (2认同)

Ima*_*tit 35

使用Swift 4,Array与其他Sequence符合协议的对象(Dictionary,Set等)一样,有两个调用的方法max(),max(by:)它们返回序列中的最大元素或者nil序列为空.


#1. Array

如果序列里面的元素类型符合max()协议(也可能是Comparable,String,Float或者您的自定义类或结构的一个),你将能够使用Character具有以下声明:

@warn_unqualified_access func max() -> Element?
Run Code Online (Sandbox Code Playgroud)

返回序列中的最大元素.

以下游乐场代码显示使用max():

let intMax = [12, 15, 6].max()
let stringMax = ["bike", "car", "boat"].max()

print(String(describing: intMax)) // prints: Optional(15)
print(String(describing: stringMax)) // prints: Optional("car")
Run Code Online (Sandbox Code Playgroud)
class Route: Comparable, CustomStringConvertible {

    let distance: Int
    var description: String { return "Route with distance: \(distance)" }

    init(distance: Int) {
        self.distance = distance
    }

    static func ==(lhs: Route, rhs: Route) -> Bool {
        return lhs.distance == rhs.distance
    }

    static func <(lhs: Route, rhs: Route) -> Bool {
        return lhs.distance < rhs.distance
    }

}

let routes = [
    Route(distance: 20),
    Route(distance: 30),
    Route(distance: 10)
]

let maxRoute = routes.max()
print(String(describing: maxRoute)) // prints: Optional(Route with distance: 30)
Run Code Online (Sandbox Code Playgroud)

#2. max()

如果序列中的元素类型不符合Array协议,则必须使用max(by:)具有以下声明:

@warn_unqualified_access func max(by areInIncreasingOrder: (Element, Element) throws -> Bool) rethrows -> Element?
Run Code Online (Sandbox Code Playgroud)

返回序列中的最大元素,使用给定谓词作为元素之间的比较.

以下游乐场代码显示使用Comparable:

let dictionary = ["Boat" : 15, "Car" : 20, "Bike" : 40]

let keyMaxElement = dictionary.max(by: { (a, b) -> Bool in
    return a.key < b.key
})

let valueMaxElement = dictionary.max(by: { (a, b) -> Bool in
    return a.value < b.value
})

print(String(describing: keyMaxElement)) // prints: Optional(("Car", 20))
print(String(describing: valueMaxElement)) // prints: Optional(("Bike", 40))
Run Code Online (Sandbox Code Playgroud)
class Route: CustomStringConvertible {

    let distance: Int
    var description: String { return "Route with distance: \(distance)" }

    init(distance: Int) {
        self.distance = distance
    }

}

let routes = [
    Route(distance: 20),
    Route(distance: 30),
    Route(distance: 10)
]

let maxRoute = routes.max(by: { (a, b) -> Bool in
    return a.distance < b.distance
})

print(String(describing: maxRoute)) // prints: Optional(Route with distance: 30)
Run Code Online (Sandbox Code Playgroud)


Sam*_*Sam 15

其他答案都是正确的,但不要忘记你也可以使用集合运算符,如下所示:

var list = [1, 2, 3, 4]
var max: Int = (list as AnyObject).valueForKeyPath("@max.self") as Int
Run Code Online (Sandbox Code Playgroud)

你也可以用同样的方式找到平均值:

var avg: Double = (list as AnyObject).valueForKeyPath("@avg.self") as Double
Run Code Online (Sandbox Code Playgroud)

这种语法可能不如其他一些解决方案清晰,但有趣的是看到-valueForKeyPath:仍然可以使用:)


Khu*_*ong 10

您可以使用reduce:

let randomNumbers = [4, 7, 1, 9, 6, 5, 6, 9]
let maxNumber = randomNumbers.reduce(randomNumbers[0]) { $0 > $1 ? $0 : $1 } //result is 9
Run Code Online (Sandbox Code Playgroud)


小智 5

对于 Swift 1.2(也许更早),您现在需要使用:

let nums = [1, 6, 3, 9, 4, 6];
let numMax = nums.reduce(Int.min, combine: { max($0, $1) })
Run Code Online (Sandbox Code Playgroud)

为了使用 Double 值,我使用了这样的东西:

let nums = [1.3, 6.2, 3.6, 9.7, 4.9, 6.3];
let numMax = nums.reduce(-Double.infinity, combine: { max($0, $1) })
Run Code Online (Sandbox Code Playgroud)


San*_*ngh 5

斯威夫特 3.0

您可以以编程方式尝试此代码。

func getSmallAndGreatestNumber() -> Void {

    let numbers = [145, 206, 116, 809, 540, 176]
    var i = 0
    var largest = numbers[0]
    var small = numbers[0]
    while i < numbers.count{

        if (numbers[i] > largest) {
            largest = numbers[i]
        }
        if (numbers[i] < small) {
            small = numbers[i]
        }
        i = i + 1
    }
    print("Maximum Number ====================\(largest)")// 809
    print("Minimum Number ====================\(small)")// 116
}
Run Code Online (Sandbox Code Playgroud)