[Swift] Array にループしてアクセスする方法

Array に範囲外のインデックスを渡しても、コレクションが繰り返されると想定して要素を返す方法を説明します。

環境&対象

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

  • macOS Monterey 12.1 beta3
  • Xcode 13.2 beta2
  • iOS 15.2

配列/Array

配列は、有限個の要素を保持しておく要素です。

Apple のドキュメントは、こちら

ランダムアクセスできる Array

ランダムアクセスと表現されますが、Array は、インデックスを使って、直接 X-番目の要素にアクセスすることができます。


let array: [Int] = [2, 3, 4, 5]
let secondValue = array[1] // [0] has first value

Array と比較すると、LinkedList と呼ばれるものは、前後の要素にのみアクセスできる構造なので、
アクセスしたい要素に直接アクセスすることはできず、先頭(もしくは最後)の要素から順番にたどることが必要となります。

# Foundation では、LinkedList は提供されていませんが、Apple が swift-collections として、公開しているライブラリを使用すると、Array/Dictionary/Set 以外のコレクションを使うことができるようになります。

順序付きコレクションとしての Array

Foundation が提供するコレクションの中で、要素の順番を保持するものとしては、Array しかありません。

また、要素の重複を許すのも、Array しかありません。Dictionary の Key は、unique であることが必要です(同じ Key を使うと上書きされます)し、Set は、重複要素を追加しても、単に無視されます。

ですので、ランダムアクセスを必要としていないケースでも コレクションとして Array を使うことは比較的多いと思います。

Array に 無限アクセスしたい

ケースによりますが、コレクションに無限的にアクセスしたいことがあります。

例えば、以下のような多くの要素をカラフルに表示したいときです。

Colorful

多くの要素があるときに、要素と同数の色を用意することは難しいので、特定の色のコレクションを繰り返し使うことになります。

ランダムに割り当てても良いのですが、同じ色が隣に来てしまうかもしれませんし、特定の順番の繰り返しを使うことが多いです。

剰余演算子を使う

取り出す側で、インデックス % 色の数 として、書くこともできます。


//
//  ContentView.swift
//
//  Created by : Tomoaki Yagishita on 2021/12/08
//  © 2021  SmallDeskSoftware
//

import SwiftUI

struct ContentView: View {
    let colors: [Color] = [.red, .blue, .green, .yellow, .orange]
    var body: some View {
        VStack {
            ForEach(0..<20) { index in
                colors[index % colors.count]
            }
        }
    }
}

動くのですが、なんとなく、(無意味に)複雑に記述している気がします。

Array の extension で subscript を定義

剰余演算子を使って アクセスするインデックスを計算する箇所を extension を使って、外部に出してしまうとコードがすっきりします。

extension を使って、subscript を追加定義できるので、そのことを利用します。


//
//  ContentView.swift
//
//  Created by : Tomoaki Yagishita on 2021/12/08
//  © 2021  SmallDeskSoftware
//

import SwiftUI

struct ContentView: View {
    let colors: [Color] = [.red, .blue, .green, .yellow, .orange]
    var body: some View {
        VStack {
            ForEach(0..<20) { index in
                colors[loopAt: index]
            }
        }
    }
}

extension Array {
    subscript(loopAt index: Int) -> Element {
        self[index % self.count]
    }
}

なお、どちらも 表示結果は同じになります。

まとめ:Array にループしてアクセスする方

Array にループしてアクセスする方
  • extension で ループしてアクセスするためのメソッド(or subscript) を定義する
  • メソッド内で、剰余演算子を使用して アクセスする

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

Swift 学習におすすめの本

詳解Swift

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

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

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

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

Swift ポケットリファレンス

Swift を学んでも、プログラミング言語の文法を全て記憶しておくことは無理なので、ちょっとした文法の確認をするために、リファレンス本を手元に置いておくと便利です。

注意
Swift4 までしか対応していないので、相違点を理解して参照する必要があります。

コメントを残す

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