Правильный способ найти 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
11 ответов:
дано:
let numbers = [1, 2, 3, 4, 5]Swift 3:
numbers.min() // equals 1 numbers.max() // equals 5Swift 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.
он может быть изменен в будущем, поэтому я предлагаю вам лучше проверить документ, прежде чем использовать эти методы.
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
Comments