[Swift] 値を特定値域に限定する / clamp

     
⌛️ < 1 min.

結構便利なのに、あまり知られていない(気がする) Range の clamped(to:) を説明します。

環境&対象

以下の環境で動作確認を行なっています。

  • macOS15.0.1 Sequoia
  • Xcode 16.1 Beta
  • iOS 18.1
  • Swift 5.9

Range

Range は、範囲を表現するための型です。
実際には、開始位置は 閉区間、終了位置は 開区間 になります。


参考
RangeApple Developer Documentation

開始/終了の両方が閉区間を表現する ClosedRange もあります。


参考
ClosedRangeApple Developer Documentation

clamped(to:)

値域を扱うときに、特定の範囲に収まるように値域を調整したいケースがあります。

Swift では、clamped(to:) というメソッドが用意されています。


参考
clamped(to:)Apple Developer Documentation

to に与えられた Range に収まるような Range を返します。

Range の(範囲の対象となる) Bound は、Comparable な型なので、その順序に応じた処理がされます。

なお、同様なメソッドが ClosedRange にも用意されています。

以下は、clamped(to:) の動作を確認した時のテストコードです。

    @Test func understandClamped() async throws {
        #expect((1..<10).clamped(to: 2..<5) == 2..<5)
        #expect((1..<10).clamped(to: 0..<3) == 1..<3)
        #expect((1..<10).clamped(to: 7..<15) == 7..<10)
        #expect((1..<10).clamped(to: 15..<25) == 15..<15)
    }

4つ目のテストで確認している “2つのRange の値域がまったく交わらない時” の挙動に少し注意が必要でしょうか。

Double/Int 等を clamp

clamp を理解すると 同様の操作を Double や Int に適用したくなります。

ですが、今のところ(?) は用意されていないようです。

以下のような感じで、extension を作ると Range と同様に適用できるようになります。

extension ClosedRange {
    public func clamp(_ value: Bound) -> Bound {
        if value < self.lowerBound {
            return self.lowerBound
        } else if self.upperBound < value {
            return self.upperBound
        }
        return value
    }
}
MEMO

max によって clamp された時の挙動を考えると、Range ではなく、ClosedRange を使うのが良い気がしたので、ClosedRange の extension にしています。
Range.max は、開区間の終端を表しているので、Range.max 自身は Range に入っているとは判断されません。
ですので、clamp した値として Range.max を返すのは悪手な気がします。

以下のようなテストコードで挙動を確認できます。

    @Test func clamp_check() async throws {
        #expect((1...3).clamp(2) == 2)
        #expect((1...3).clamp(5) == 3)
        #expect((1...3).clamp(-2) == 1)
    }

まとめ

Range/ClosedRange の clampedを確認し、Double/Int 等にも同様の処理ができるようにしてみました。

値を値域に限定する clamp
  • Range/ ClosedRange のどちらにも clamped(to:) が用意されていて、値域を限定できる
  • Double/ Int 等には用意されていないので、自分で実装を用意することが必要
  • 自分で用意するときには、ClosedRange の extension にするのがおすすめ

説明は以上です。
不明な点やおかしな点ありましたら、こちらまで。

SwiftUI おすすめ本

SwiftUI を理解するには、以下の本がおすすめです。

SwiftUI ViewMatery

SwiftUI で開発していくときに、ViewやLayoutのための適切なmodifierを探すのが大変です。
英語での説明になってしまいますが、以下の”SwiftUI Views Mastery Bundle”という本がビジュアル的に確認して探せるので、便利です。

英語ではありますが、1ページに コードと画面が並んでいるので、非常にわかりやすいです。

View に適用できる modifier もわかりやすく説明されているので、ビューの理解だけではなく、どのような装飾ができるかも簡単にわかります。

超便利です

SwiftUIViewsMastery

販売元のページは、こちらです。

SwiftUI 徹底入門

# SwiftUI は、毎年大きく改善されていますので、少し古くなってしまいましたが、いまでも 定番本です。

Swift学習におすすめの本

詳解Swift

Swift の学習には、詳解 Swift という書籍が、おすすめです。

著者は、Swift の初期から書籍を出していますし、Swift の前に主力言語だった Objective-C という言語についても同様の書籍を出しています。

最新版を購入するのがおすすめです。

現時点では、上記の Swift 5 に対応した第5版が最新版です。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です