SwiftのRangeを完全解説!初心者向けの12選コード集

SwiftのRangeを学ぶ人のシルエットとコードのスクリーンショットSwift
この記事は約20分で読めます。

 

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

基本的な知識があればカスタムコードを使って機能追加、目的を達成できるように作ってあります。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を凌駕する現役のプログラマチームによって監修されています。

サイト内のコードを共有する場合は、参照元として引用して下さいますと幸いです

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

はじめに

SwiftはAppleが開発したプログラミング言語で、iOSやmacOSなどのAppleプラットフォーム上のアプリケーション開発に使用されます。

近年、多くの開発者に支持されていますが、それには理由があります。その中で特に注目されているのが「Range」の機能です。

Rangeは非常に便利な機能であり、日常のコーディング作業において頻繁に使用されます。

本記事では、そのRangeの使い方や特徴、応用例、注意点を深堀して説明します。

●Swiftとは

Swiftは、Appleが2014年に発表したプログラミング言語であり、Objective-Cの後継として導入されました。

これまでのObjective-Cの良さを継承しつつ、モダンで読みやすく、より安全性が高い言語として設計されています。

○Swiftの基本的な特徴

Swiftの言語設計には、次のような特徴があります。

  1. 型安全性:Swiftは型推論をサポートしており、コンパイル時に型の誤りを発見しやすくなっています。
  2. 高性能:最適化されたコンパイラにより、高速な実行が可能です。
  3. モダンな文法:クリーンで明確な構文を持ち、読み書きが容易です。
  4. メモリ安全性:自動参照カウント(ARC)によるメモリ管理を採用しているため、メモリリークのリスクを低減します。

○Swiftが支持される理由

Swiftが多くの開発者から支持される背景には、いくつかの理由があります。

  1. 直感的な文法:Swiftの文法は直感的であり、初心者にも理解しやすいです。
  2. 安全性:Swiftは安全性を第一に設計されており、不具合やバグを減少させるための多くの機能が組み込まれています。
  3. 強力な標準ライブラリ:多くの便利な関数やデータ型が標準で提供されており、開発の効率が向上します。
  4. 豊富なドキュメント:Apple公式のドキュメントは詳細で、学習リソースも豊富に提供されています。
  5. 活発なコミュニティ:世界中の多くの開発者がSwiftを使用しており、質問や疑問点についても迅速に対応してもらえる環境が整っています。

●Rangeとは

Rangeは、Swiftにおいて連続する一連の値を表すための型です。

これは、例えば数値の範囲や文字列内の特定の位置の範囲など、さまざまな文脈で使用されます。

○Rangeの定義と基本構造

Rangeの基本的な構造は、開始値と終了値で定義されます。

Swiftでは、範囲を表すために「ClosedRange」と「Range」の2つの主な型が実装されています。

このコードではClosedRangeを使って1から5までの範囲を表しています。

let closedRange = 1...5

この例では、変数closedRangeに1から5までの全ての値を含む範囲が代入されています。

一方、Rangeは終了値を含まない範囲を表します。

let halfOpenRange = 1..<5

この例では、変数halfOpenRangeに1から4までの値を含む範囲が代入されています。

●SwiftでのRangeの使い方

SwiftのRangeは、連続する値の範囲を表現するためのもので、多くのプログラムにおいて非常に役立つツールとなっています。

特に配列や文字列の部分的な操作に際して、Rangeは非常に有用です。

ここでは、SwiftでのRangeの基本的な使い方を2つのサンプルコードを交えながら説明します。

○サンプルコード1:単純なRangeの作成

SwiftでRangeを作成するための基本的な方法を紹介します。

let simpleRange = 1..<5
print(simpleRange)

このコードでは、1から4までの範囲を示すRangeを作成しています。

この例では、1を始点とし、5を終点とする範囲を示していますが、5は含まれません。

実際にこのコードを実行すると、出力結果として「1..<5」と表示されます。

SwiftでのRangeを作成する際のシンボル..<は、終点を含まない範囲を表します。

このようなRangeはHalfOpenRangeと呼ばれます。

このサンプルコードを実行すると、次の結果が得られます。

「1..<5」という文字列がコンソールに表示され、1から4までの範囲を表現するRangeが正しく作成されたことが確認できます。

○サンプルコード2:Rangeを使った配列のスライス

次に、Rangeを使って配列から部分的に要素を取得する方法を表すコードを紹介します。

let fruits = ["apple", "banana", "cherry", "date", "elderberry"]
let selectedFruits = fruits[1..<4]
print(selectedFruits)

このコードでは、fruitsという名前の配列に5つのフルーツの名前が格納されています。

この例では、2番目から4番目までのフルーツを新しい配列selectedFruitsにスライスとして格納しています。

実行すると、出力結果としては、[“banana”, “cherry”, “date”]という配列が得られます。

これにより、Rangeを使って配列から指定した範囲の要素を効率的に取得できることがわかります。

○サンプルコード3:Rangeを使った文字列の部分取得

Swiftの文字列操作では、Rangeを用いて特定の部分を取り出すことができます。

ここではその基本的な方法を表すサンプルコードを紹介します。

let 文字列 = "SwiftのRangeを学びましょう"
if let 範囲 = 文字列.range(of: "Range") {
    let 取得文字列 = 文字列[範囲]
    print(取得文字列)
}

このコードでは、”SwiftのRangeを学びましょう”という文字列の中から”Range”という部分を探し、その範囲を取得しています。

取得した範囲を元の文字列に適用することで、”Range”という部分文字列を得ることができます。

この例を実行すると、コンソールに”Range”と表示されます。

○サンプルコード4:ClosedRangeとHalfOpenRangeの違い

SwiftのRangeには、ClosedRangeとHalfOpenRangeという二つの主要な型があります。

これらの型は、範囲の終端を含むか含まないかの違いによって区別されます。

ここでは、ClosedRangeとHalfOpenRangeの基本的な使い方を表すサンプルコードを紹介します。

// ClosedRange: 範囲の両端を含む
let 閉区間 = 1...5
print(閉区間.contains(5))  // trueを返す

// HalfOpenRange: 範囲の終端を含まない
let 半開区間 = 1..<5
print(半開区間.contains(5))  // falseを返す

このコードでは、1から5までのClosedRangeとHalfOpenRangeをそれぞれ定義しています。

ClosedRangeは範囲の両端を含むため、5はその範囲内に存在します。

一方、HalfOpenRangeは範囲の終端を含まないため、5はその範囲内に存在しません。

この例を実行すると、コンソールには「true」と次に「false」と表示されます。

●SwiftのRangeの応用例

SwiftのRangeは単に範囲を表すだけでなく、多岐にわたる応用例があります。

ここでは、SwiftでのRangeの応用例をいくつか紹介し、サンプルコードとその説明を交えながら解説していきます。

○サンプルコード5:Rangeを活用したfor-inループ

Swiftではfor-inループを使用して、特定の範囲の数値を繰り返し処理することができます。

この時、Rangeを利用して繰り返しの範囲を指定することができます。

ここでは、Rangeを使用して1から5までの数字を出力するサンプルコードを紹介します。

for i in 1..<6 {
    print(i)
}

このコードでは1..<6を使って1から5までの範囲を指定しています。

この例では、..<を使ってHalfOpenRangeを生成して、1から5までの数字を繰り返し出力しています。

このコードを実行すると、下記のように1から5までの数字が順に出力されます。

1
2
3
4
5

○サンプルコード6:Rangeによる条件式の作成

Rangeを使用して、特定の値がある範囲に含まれるかどうかをチェックすることもできます。

このような機能は、条件式の中で非常に役立ちます。

ここでは、ある数値が指定した範囲内にあるかどうかを判定するサンプルコードを紹介します。

let age = 25
if 20..<30 ~= age {
    print("20代です。")
} else {
    print("20代ではありません。")
}

このコードでは、20..<30を使って20から29までの範囲を指定しています。

また、~=オペレータを使って、ageがこの範囲内にあるかどうかを判定しています。

この例では、ageが25なので、”20代です。”と出力されます。

このコードを実行すると、下記のメッセージが表示されます。

20代です。

○サンプルコード7:Rangeを使った関数の定義

SwiftのRangeは、関数の定義においても役立ちます。

特定の範囲の数値を受け取る関数を作成する場合、Rangeを活用して関数の引数として指定することができます。

下記のコードは、Rangeを使って、ある範囲内の数値を受け取り、その範囲内の合計値を返す関数を定義しています。

func sumWithinRange(range: Range<Int>) -> Int {
    var total = 0
    for i in range {
        total += i
    }
    return total
}

let result = sumWithinRange(range: 1..<5)

このコードでは、sumWithinRangeという関数を定義しています。

この関数はRange型の引数を受け取り、その範囲内のすべての整数を加算して、結果を返します。

この例では、1から4までの数値の合計値を求めています。

このコードを実行すると、result変数には10という値が格納されます。

なぜなら、1 + 2 + 3 + 4 = 10だからです。

○サンプルコード8:Rangeを活用した配列のフィルタリング

Swiftの配列は、Rangeを活用して特定の要素を取得したり、特定の範囲に基づいて要素をフィルタリングすることができます。

下記のコードは、Rangeを利用して配列から特定の範囲の要素を取り出して新しい配列を作成する例を表しています。

let numbers = [2, 5, 8, 13, 21, 34, 55, 89]
let subrange = numbers[2..<6]

このコードでは、初めに8つの要素を持つ整数の配列numbersを定義しています。

その後、2..<6というRangeを使って、3番目から6番目までの要素を取り出してsubrangeに格納しています。

このコードを実行すると、subrange変数には[8, 13, 21, 34]という新しい配列が格納されます。

Swiftの配列は0から始まるため、Rangeの開始位置は2で3番目の要素、終了位置は5で6番目の要素の直前までを取得することになります。

○サンプルコード9:Strideを組み合わせたRangeの活用

SwiftのRangeは、繰り返しや範囲指定の際に非常に役立つ機能ですが、単独では一定の間隔で繰り返すことが難しい場面もあります。

こういった場面での解決策として、stride関数を組み合わせる方法があります。

このコードでは、strideを使って特定の間隔での数値の範囲を生成するコードを表しています。

この例では、1から10までの数値を2つ飛ばしで取得しています。

for i in stride(from: 1, to: 10, by: 2) {
    print(i)  // このコメントは1,3,5,7,9が順に出力されることを示す
}

このコードを実行すると、1,3,5,7,9という数字が順番に出力されます。

stride関数のfromで開始地点、toで終了地点を指定し、byで間隔を設定します。

このように、Strideを組み合わせることで、Rangeだけでは表現しにくい独自の範囲や間隔の繰り返しも実現できるようになります。

○サンプルコード10:Rangeを使ったSwitch文の範囲指定

SwiftのSwitch文は、値を検証し、その値に応じて異なるコードブロックを実行するための強力なツールです。

特に、SwiftのRangeを使用すると、Switch文のcase内で範囲を指定することが可能です。

このコードでは、ある整数値を判定し、それがどの範囲に属するかを判定するコードを表しています。

この例では、整数値が1から5の間にあるか、6から10の間にあるか、それ以外の場合にどのように動作するかを定義しています。

let value = 7

switch value {
case 1...5:
    print("値は1から5の間です。")  // このコメントは、valueが1~5の間の場合に出力されることを示す
case 6...10:
    print("値は6から10の間です。")  // このコメントは、valueが6~10の間の場合に出力されることを示す
default:
    print("値は指定された範囲外です。")  // このコメントは、valueが上記の範囲以外の場合に出力されることを示す
}

このコードを実行すると、「値は6から10の間です。」というメッセージが出力されます。

Rangeを活用することで、Switch文の中で幅広い範囲を持つ条件を簡潔に表現することができ、コードの可読性や保守性を向上させることができます。

○サンプルコード11:Rangeのカスタム拡張

Swiftの強力な特徴の1つは、既存の型を拡張して新しいメソッドやプロパティを追加することができる点です。

これにより、開発者はRange型に自分のニーズに合わせて新しい機能を追加することができます。

このコードでは、Rangeに新しいメソッドcontainsMultiple(of:)を追加しています。

この例では、指定された数の倍数がRange内に存在するかどうかを判断する機能を持つメソッドを追加しています。

extension Range where Bound: Numeric {
    func containsMultiple(of number: Bound) -> Bool {
        for value in self {
            if value % number == 0 {
                return true
            }
        }
        return false
    }
}

let range = 1..<10
print(range.containsMultiple(of: 3))  // trueを出力

上記のコードを見てみると、Rangeを拡張してcontainsMultiple(of:)メソッドを追加しています。

このメソッドは、指定した数の倍数がRange内に存在するかどうかを確認するためのものです。

例として、1から9までのRangeで3の倍数が存在するかどうかを確認しています。

この場合、3、6、9という3の倍数が存在するので、trueが出力されます。

○サンプルコード12:Rangeを活用したデータのソート

Rangeを使用して、特定の範囲内のデータをソートする方法もあります。

特に大きなデータセットがある場合、全てのデータをソートするのではなく、特定の範囲だけをピックアップしてソートすることが効率的です。

このコードでは、配列の中から特定のRange内のデータだけを取得し、それをソートする例を表しています。

この例では、5番目から8番目までの要素を取得してソートしています。

let numbers = [3, 7, 2, 8, 5, 6, 1, 4, 9]
let sortingRange = 5..<8
let sortedSubset = numbers[sortingRange].sorted()
print(sortedSubset)  // [1, 4, 6]を出力

上記のコードを詳しく見てみると、まず数字の配列numbersが定義されています。

次に、ソートを行いたい範囲としてsortingRangeを定義して、この範囲内のデータを取得してソートします。

ソート結果として、5番目から8番目までの要素、すなわち5, 6, 1の数値が昇順にソートされた[1, 4, 6]が出力されます。

●Rangeの注意点と対処法

SwiftのRangeは非常に強力で多様な使い方ができる一方、その使用に当たっていくつかの注意点が存在します。

これらの注意点を理解し、適切な対処をすることで、より安全にSwiftのRangeを活用することが可能です。

ここでは、Rangeの主要な注意点とそれに対する対処法について詳細に解説していきます。

○文字列のRange使用時の罠

Swiftで文字列の部分取得や操作を行う際、Rangeを利用することがよくあります。

しかし、文字列のRangeは、特に日本語や絵文字などのマルチバイト文字を扱う場合、直感的でない振る舞いをすることがあります。

このコードでは、文字列から一部の文字をRangeを使って取得するコードを表しています。

この例では、”こんにちは🌸”という文字列から、4文字目から6文字目までを取得しています。

let greeting = "こんにちは🌸"
let range = greeting.index(greeting.startIndex, offsetBy: 3)..<greeting.index(greeting.startIndex, offsetBy: 6)
let result = greeting[range]
print(result) // 出力結果を確認します。

上記のコードを実行すると、”さ🌸”という結果が出力されます。

このように、絵文字は2文字分としてカウントされるため、予想外の結果となることがあります。

対処法として、文字列の操作を行う際は、文字列の実際の文字数や、マルチバイト文字の存在を考慮することが重要です。

countプロパティを利用して文字列の長さを確認したり、utf16プロパティを利用してマルチバイト文字を適切にカウントする方法などがあります。

○Rangeの上限と下限の扱い

Rangeには上限と下限が存在します。

特に、ClosedRangeRangeHalfOpenRange)との違いに注意が必要です。

このコードでは、ClosedRangeRangeの違いを表しています。

この例では、1から5までの整数を取得するためのRangeをそれぞれ作成しています。

let closedRange: ClosedRange<Int> = 1...5
let halfOpenRange: Range<Int> = 1..<6
print(closedRange) // 出力結果を確認します。
print(halfOpenRange) // 出力結果を確認します。

上記のコードを実行すると、closedRange1...5halfOpenRange1..<6という結果が出力されます。

対処法として、どちらのRangeも使い方に応じて活用できますが、使用する場面や目的に応じて適切なRangeの形式を選択することが大切です。

特に、配列のスライスや部分取得の際には、存在しないインデックスを指定しないよう注意が必要です。

○Rangeと他の型との相互変換時の注意

Rangeを他の型、例えばArrayやStringといったコレクションと相互変換する際には、いくつかの注意が必要です。

このコードでは、配列の部分をRangeを使用して取得し、新たな配列として返すコードを表しています。

この例では、[1,2,3,4,5]という配列から、2番目から4番目までの要素を取得しています。

let numbers = [1, 2, 3, 4, 5]
let range = 1..<4
let slicedNumbers = Array(numbers[range])
print(slicedNumbers) // 出力結果を確認します。

上記のコードを実行すると、[2,3,4]という結果が得られます。

対処法として、配列や文字列を操作する際、Rangeを直接使用することができますが、返り値がコレクションの一部として得られるため、必要に応じてArrayやStringなどの型へ変換することが求められます。

このような変換時には、Rangeの上限や下限を超えるような操作を避け、存在する範囲内での操作を心がけることが重要です。

●Rangeのカスタマイズ方法

SwiftのRangeを使っていると、標準の機能だけでは物足りない場面も出てきます。

そんな時、Rangeをカスタマイズする方法を学べば、より柔軟にSwiftのRangeを活用できるようになります。

ここでは、カスタムRangeの作成方法やRangeの操作を拡張するメソッドの追加方法を中心に、実用的なサンプルコードを交えて詳細に解説していきます。

○カスタムRangeの作成

Swiftでは、既存のRangeを基に新しいカスタムRangeを作成することができます。

例として、特定のステップ間隔で整数の範囲を生成するカスタムRangeを考えてみましょう。

このコードでは、ステップ間隔を指定してRangeを生成するカスタムRangeを表しています。

この例では、1から10までの整数の範囲を2のステップ間隔で生成しています。

struct SteppedRange: Sequence {
    let start: Int
    let end: Int
    let step: Int

    init(start: Int, end: Int, step: Int = 1) {
        self.start = start
        self.end = end
        self.step = step
    }

    func makeIterator() -> AnyIterator<Int> {
        var current = start
        return AnyIterator {
            if current > self.end {
                return nil
            }
            let returnValue = current
            current += self.step
            return returnValue
        }
    }
}

let customRange = SteppedRange(start: 1, end: 10, step: 2)
for num in customRange {
    print(num)
}

上記のコードを実行すると、1, 3, 5, 7, 9という数列が出力されます。

このように、ステップ間隔を指定して整数の範囲をカスタムに生成することができました。

○Rangeの操作を拡張するメソッドの追加

次に、既存のRange型に新しい操作を追加する方法を見ていきます。

例えば、Rangeの各要素を2倍にするメソッドを追加したいとします。

このコードでは、Rangeの各要素を2倍にする拡張メソッドを表しています。

この例では、1から5までの範囲の各要素を2倍にしています。

extension Range where Bound == Int {
    func doubleElements() -> [Int] {
        return self.map { $0 * 2 }
    }
}

let originalRange = 1..<6
let doubledValues = originalRange.doubleElements()
print(doubledValues)

このコードを実行すると、[2, 4, 6, 8, 10]という結果が出力されます。

Rangeの各要素を2倍にする拡張メソッドを追加することで、より柔軟な操作が可能になりました。

まとめ

SwiftのRangeは非常に強力で柔軟なツールです。

基本的な使い方から、カスタムRangeの作成、そしてRangeの操作を拡張するメソッドの追加まで、多彩な方法でRangeを利用することができます。

この記事を通じて、Rangeの持つ可能性やカスタマイズ方法について深く理解できたことでしょう。

日常のプログラミングにおいて、この知識を活かして効率的かつ柔軟なコーディングを進めていきましょう。