Правильный способ найти max в массиве в Swift



у меня до сих пор есть простой (но потенциально дорогой) способ:



var myMax = sort(myArray,>)[0]


и как меня учили это делать в школе:



var myMax = 0
for i in 0..myArray.count {
if (myArray[i] > myMax){myMax = myArray[i]}
}


есть ли лучший способ получить максимальное значение из целочисленного массива в Swift? В идеале что-то, что является одной строкой, такой как Ruby's .max

694   11  

11 ответов:

дано:

let numbers = [1, 2, 3, 4, 5]

Swift 3:

numbers.min() // equals 1
numbers.max() // equals 5

Swift 2:

numbers.minElement() // equals 1
numbers.maxElement() // equals 5

обновление:этой вероятно, должен быть принят ответ, так как maxElement появился в Swift.


использовать всемогущий reduce:

let nums = [1, 6, 3, 9, 4, 6];
let numMax = nums.reduce(Int.min, { max(, ) })

так же:

let numMin = nums.reduce(Int.max, { min(, ) })

reduce принимает первое значение, которое является начальным значением для внутренней переменной аккумулятора, затем применяет переданную функцию (здесь она анонимна) к аккумулятору и каждому элементу массива последовательно и сохраняет новое значение в аккумулятор. Затем возвращается последнее значение аккумулятора.

С Swift 4, Array, как и другие Sequence объекты, соответствующие протоколу (Dictionary,Set и т. д.), имеет два метода называют max() и max(by:) что возвращает максимальный элемент в последовательности или nil если последовательность пуста.


#1. max()

если тип элемента внутри вашей последовательности соответствует Comparable протокол (может быть String,Float,Character или один из ваших пользовательских классов или структур), вы сможете использовать max() это имеет следующее декларация:

@warn_unqualified_access func max() -> Element?

возвращает максимальный элемент в последовательности.

следующие коды игровой площадки показывают, чтобы использовать 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")
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)

#2. max(by:)

если тип элемента внутри вашей последовательности не соответствует Comparable протокол, вам придется использовать max(by:), который имеет следующие декларация:

@warn_unqualified_access func max(by areInIncreasingOrder: (Element, Element) throws -> Bool) rethrows -> Element?

возвращает максимальный элемент в последовательности, используя данный предикат в качестве сравнения между элементами.

следующие коды игровой площадки показывают, чтобы использовать max(by:):

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))
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)

другие ответы все правильные, но не забывайте, что вы также можете использовать операторы сбора, как показано ниже:

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

вы также можете найти среднее значение таким же образом:

var avg: Double = (list as AnyObject).valueForKeyPath("@avg.self") as Double

этот синтаксис может быть менее ясным, чем некоторые другие решения, но интересно видеть, что -valueForKeyPath: еще можно использовать :)

можно использовать reduce:

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

С Swift 1.2 (а может и раньше) теперь вам нужно использовать:

let nums = [1, 6, 3, 9, 4, 6];
let numMax = nums.reduce(Int.min, combine: { max(, ) })

для работы с двойными значениями я использовал что-то вроде этого:

let nums = [1.3, 6.2, 3.6, 9.7, 4.9, 6.3];
let numMax = nums.reduce(-Double.infinity, combine: { max(, ) })

в Swift 2.0,minElement и maxElement стать способы SequenceType протокол, вы должны называть их так:

let a = [1, 2, 3]
print(a.maxElement()) //3
print(a.minElement()) //1

используя maxElement как функция, как maxElement(a) и недоступен сейчас.

синтаксис Swift находится в движении, поэтому я могу просто подтвердить это в Xcode version7 beta6.

он может быть изменен в будущем, поэтому я предлагаю вам лучше проверить документ, прежде чем использовать эти методы.

var numbers = [1, 2, 7, 5];    
var val = sort(numbers){ > }[0];

Swift 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
}

обновлено для Swift 3/4:

используйте ниже простые строки кода, чтобы найти максимум из массива;

var num = [11, 2, 7, 5, 21]
var result = num.sorted(){
     > 
}
print("max from result: \(result[0])") // 21

вы также можете сортировать массив, а затем использовать array.first или array.last

Comments

    Ничего не найдено.