Swift equivalent for MIN and MAX macros
GenericsSwiftGenerics Problem Overview
In C / Objective-C it is possible to find the minimum and maximum value between two numbers using MIN and MAX macros. Swift doesn't support macros and it seems that there are no equivalents in the language / base library. Should one go with a custom solution, maybe based on generics like this one?
Generics Solutions
Solution 1 - Generics
min
and max
are defined in Swift:
func max<T : Comparable>(x: T, y: T, rest: T...) -> T
func min<T : Comparable>(x: T, y: T, rest: T...) -> T
and used like so:
let min = min(1, 2)
let max = max(1, 2)
See this great writeup on documented & undocumented built-in functions in Swift.
Solution 2 - Generics
As pointed out, Swift provides max
and min
functions.
An example (updated for Swift 2.x).
let numbers = [ 1, 42, 5, 21 ]
var maxNumber = Int()
for number in numbers {
maxNumber = max(maxNumber, number as Int)
}
print("the max number is \(maxNumber)") // will be 42
Solution 3 - Generics
With Swift 5, max(_:_:)
and min(_:_:)
are part of the Global Numeric Functions. max(_:_:)
has the following declaration:
func max<T>(_ x: T, _ y: T) -> T where T : Comparable
You can use it like this with Int
s:
let maxInt = max(5, 12) // returns 12
Also note that there are other functions called max(_:_:_:_:)
and min(_:_:_:_:)
that allows you to compare even more parameters. max(_:_:_:_:)
has the following declaration:
func max<T>(_ x: T, _ y: T, _ z: T, _ rest: T...) -> T where T : Comparable
You can use it like this with Float
s:
let maxInt = max(12.0, 18.5, 21, 26, 32.9, 19.1) // returns 32.9
With Swift however, you're not limited to use max(_:_:)
and its siblings with numbers. In fact, those functions are generic and can accept any parameter type that conforms to Comparable
protocol, may it be String
, Character
or one of your custom class
or struct
.
Thereby, the following Playground sample code works perfectly:
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 route1 = Route(distance: 4)
let route2 = Route(distance: 8)
let maxRoute = max(route1, route2)
print(maxRoute) // prints "Route with distance: 8"
Furthermore, if you want to get the min/max element of elements that are inside an Array
, a Set
, a Dictionary
or any other sequence of Comparable
elements, you can use the max() or the min() methods (see this Stack Overflow answer for more details).
Solution 4 - Generics
SWIFT 4 Syntax changed a bit:
public func max<T>(_ x: T, _ y: T) -> T where T : Comparable
public func min<T>(_ x: T, _ y: T) -> T where T : Comparable
and
public func max<T>(_ x: T, _ y: T, _ z: T, _ rest: T...) -> T where T : Comparable
public func min<T>(_ x: T, _ y: T, _ z: T, _ rest: T...) -> T where T : Comparable
So when you use it you should write like in this example:
let min = 0
let max = 100
let value = -1000
let currentValue = Swift.min(Swift.max(min, value), max)
So you get the value from 0 to 100 don't matter if is it below 0 or higher 100.
Solution 5 - Generics
Try this:
let numbers = [2, 3, 10, 9, 14, 6]
let min = numbers.min()
let max = numbers.max()
print("Max = \(max) Min = \(min)")