Given:
let a = 4.2
let b = -1.3
let c = 6.4
I want to know the simplest, Swiftiest way to clamp these values to a given range, say 0...
The ClosedInterval type already has a
func clamp(_ intervalToClamp: ClosedInterval) -> ClosedInterval
method which takes another interval as an argument. There is a proposal on the Swift evolution mailing list
to add another method which clamps a single value to the given interval:
/// Returns `value` clamped to `self`.
func clamp(value: Bound) -> Bound
and that is exactly what you need.
Using the implementation of the existing clamp()
method at
as an example, this additional clamp()
method can be implemented as
extension ClosedInterval {
func clamp(value : Bound) -> Bound {
return self.start > value ? self.start
: self.end < value ? self.end
: value
}
}
Example:
(0.0 ... 5.0).clamp(4.2) // 4.2
(0.0 ... 5.0).clamp(-1.3) // 0.0
(0.0 ... 5.0).clamp(6.4) // 5.0
ClosedInterval
is a generic type
public struct ClosedInterval { ... }
therefore this works not only for Double
but for all
types which are Comparable
(like Int
, CGFloat
, String
, ...):
(1 ... 3).clamp(10) // 3
("a" ... "z").clamp("ä") // "ä"
Update for Swift 3 (Xcode 8): ClosedInterval
has been renamed
to ClosedRange
, and its properties are lower/upperBound
now:
extension ClosedRange {
func clamp(_ value : Bound) -> Bound {
return self.lowerBound > value ? self.lowerBound
: self.upperBound < value ? self.upperBound
: value
}
}