Swiftで学ぶ2次元配列の使い方12選!

Swiftの2次元配列の使い方を図解したイメージSwift
この記事は約22分で読めます。

 

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

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

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

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

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

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

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

はじめに

Swiftを学ぶ上で、2次元配列は非常に重要なデータ構造の一つです。

特にゲーム開発やデータ分析など、多くの場面で活躍します。

本記事では、Swiftにおける2次元配列の使い方を、12の具体的なサンプルコードとともに解説します。

初心者の方も手順を追って学び、2次元配列をマスターしましょう。

●2次元配列とは?

2次元配列は、言葉通り、配列の中に配列が含まれるデータ構造を指します。

一般的に行と列の形式で表現されることが多いです。

例えば、表計算ソフトのスプレッドシートのような形で、行と列の交差点にデータが配置されるイメージです。

○基本的な2次元配列の概念

通常の1次元配列では、連続したデータを格納します。

2次元配列では、それがさらに拡張され、各要素が1次元の配列として格納されています。

このような構造を持つため、2次元のグリッドやマトリックスとしてデータを扱うことができます。

○Swiftにおける2次元配列の宣言方法

Swiftで2次元配列を宣言する際の基本的な構文は次の通りです。

var 配列名: [[データ型]] = [[要素1_1, 要素1_2, ...], [要素2_1, 要素2_2, ...], ...]

このコードでは、変数名「配列名」で2次元配列を宣言しています。

[[データ型]]の部分で、2次元配列であることを示しており、内側の[データ型]が1次元配列を表しています。

この例では、複数の1次元配列を,で区切って2次元配列として格納しています。

具体的な例として、整数型の2次元配列を宣言する場合は次のようになります。

var matrix: [[Int]] = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

このコードでは、3×3の整数型2次元配列を「matrix」という変数に格納しています。

この例では、1, 2, 3が1つ目の1次元配列、4, 5, 6が2つ目の1次元配列、7, 8, 9が3つ目の1次元配列となります。

こちらの2次元配列を利用すると、例えばmatrix[0][2]と指定することで、1行目の3列目の要素3を取得することができます。

このように2次元配列は、行と列のインデックスを指定して、特定の位置の要素にアクセスすることができます。

●2次元配列の使い方

2次元配列は、配列の中にさらに配列を持つデータ構造を指します。

これにより、表形式のデータや行列などを表現することができます。

Swiftでは、2次元配列も簡単に扱うことができます。

ここでは、Swiftでの2次元配列の基本的な使い方を、サンプルコードを交えて詳しく解説していきます。

○サンプルコード1:2次元配列の宣言と初期化

このコードでは、2次元配列を宣言し、初期化する方法を表しています。

この例では、Int型の2次元配列を宣言し、その中に具体的な数字のリストを格納しています。

// 2次元配列の宣言と初期化
var array2D: [[Int]] = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]

上記の2次元配列では、3×3の行列が形成されています。

つまり、3つの配列が格納され、それぞれの配列には3つのInt型の要素が含まれています。

実際にこのコードを実行すると、array2Dには上記の数字のリストが格納されることになります。

○サンプルコード2:2次元配列への要素の追加

2次元配列への要素の追加も、1次元配列と同様に行うことができます。

このコードでは、2次元配列に新しい配列を追加する方法と、既存の配列に新しい要素を追加する方法を表しています。

// 既存の2次元配列
var array2D: [[Int]] = [
    [1, 2, 3],
    [4, 5, 6]
]

// 新しい配列を追加
array2D.append([7, 8, 9])

// 既存の配列に新しい要素を追加
array2D[0].append(4)

このコードを実行すると、array2Dは次のような内容になります。

[
    [1, 2, 3, 4],
    [4, 5, 6],
    [7, 8, 9]
]

最初に、新しい配列[7, 8, 9]array2Dの末尾に追加しました。その後、array2Dの最初の配列に、新しい要素4を追加しました。

このように、2次元配列でも要素の追加や編集が柔軟に行えます。

○サンプルコード3:2次元配列からの要素の取得

Swiftにおける2次元配列は、配列の中にさらに配列が格納されている形となります。

このような2次元配列をうまく扱うためには、要素の取得方法を理解することが必要です。

要素の取得は、日常的にアプリケーション開発を行う上で頻繁に遭遇する操作の一つとなるため、正確な方法で取得できることが求められます。

2次元配列から特定の要素を取得する際は、最初のインデックスで外側の配列を指定し、次のインデックスで内側の配列の要素を指定します。

これにより、所望のデータを正確に取り出すことができます。

ここでは、2次元配列から特定の要素を取得するためのサンプルコードを表しています。

// 2次元配列の宣言と初期化
let array2D: [[Int]] = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

// 2行目(インデックスは1から始まるため)の3つ目の要素(インデックス2)を取得
let value = array2D[1][2]
print(value)

このコードでは、整数を要素とする2次元配列を初期化しています。

そして、2行目の3つ目の要素を取得するコードを記述しています。

この例では、array2D[1][2]によって、2行目の3つ目の要素、すなわち数字の「6」を取得しています。

上記のサンプルコードを実行すると、出力として数字の「6」が表示されます。

さらに、Swiftでは配列のインデックスは0から始まるので、1行目はarray2D[0]、1行目の1つ目の要素はarray2D[0][0]といった形で取得することができます。

○サンプルコード4:2次元配列の要素を編集する方法

2次元配列の要素を編集する際も、要素の取得と同様の方法でインデックスを指定して行います。

具体的には、対象の要素に新しい値を代入することで、2次元配列の要素を編集することができます。

ここでは、2次元配列の特定の要素を編集するためのサンプルコードを紹介します。

// 2次元配列の宣言と初期化
var mutableArray2D: [[Int]] = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

// 2行目の3つ目の要素を10に変更
mutableArray2D[1][2] = 10
print(mutableArray2D[1])

このコードでは、変更可能な2次元配列を初期化しています。

その後、2行目の3つ目の要素を数字の「10」に変更しています。

この例では、mutableArray2D[1][2] = 10によって、元々の値「6」が「10」に変更されています。

上記のサンプルコードを実行すると、出力として配列[4, 5, 10]が表示されます。

○サンプルコード5:2次元配列の要素を削除する方法

2次元配列から特定の要素を削除する方法について解説します。

2次元配列では、要素の位置を指定して、その位置にある要素を削除することができます。

var matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]
matrix[1].remove(at: 1)
print(matrix)

このコードでは、matrixという名前の2次元配列を宣言して初期化しています。

この例では、matrix[1]が表す2つ目の配列から、remove(at:)メソッドを使って1番目の要素(5)を削除しています。

実際にこのコードを実行すると、matrixの内容は次のようになります。

[
    [1, 2, 3],
    [4, 6],
    [7, 8, 9]
]

2つ目の配列から5という要素が無くなり、他の要素はそのまま保持されています。

○サンプルコード6:2次元配列を使った繰り返し処理

2次元配列の要素にアクセスする際、一つ一つの要素を取り出して何らかの処理をする場合、繰り返し処理を使用します。

Swiftではfor-inループを使用して、2次元配列の各要素に簡単にアクセスすることができます。

let matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]

for row in matrix {
    for value in row {
        print(value)
    }
}

このコードでは、matrixという2次元配列の各要素にアクセスして、それぞれの要素を表示しています。

この例では、まず外側のfor-inループでmatrixの各配列(行)にアクセスし、内側のfor-inループでその配列の各要素にアクセスしています。

このコードを実行すると、次の出力が得られます。

1
2
3
4
5
6
7
8
9

上記の通り、2次元配列の各要素が順番に表示されます。

繰り返し処理を使用することで、2次元配列の各要素に簡単にアクセスし、それぞれの要素に対して何らかの処理を行うことができます。

●2次元配列の応用例

2次元配列は、単純なリストやテーブルのデータを扱うだけでなく、様々な応用例で使用されます。

これから、2次元配列を用いて行列の加算や転置を行う具体的なサンプルコードを通じて、実践的な使い方を学んでいきましょう。

○サンプルコード7:2次元配列を使った行列の加算

行列の加算は、同じ位置にある要素同士を足し合わせる操作です。

2次元配列を使用すると、このような計算を簡単に実装することができます。

ここでは、2つの2×2行列を加算するサンプルコードを紹介します。

var matrix1 = [[1, 2], [3, 4]]
var matrix2 = [[2, 3], [4, 5]]
var resultMatrix = [[0, 0], [0, 0]]

for i in 0..<2 {
    for j in 0..<2 {
        resultMatrix[i][j] = matrix1[i][j] + matrix2[i][j]
    }
}

print(resultMatrix)

このコードでは、2つの2次元配列matrix1matrix2の要素を一つずつ取り出し、その和をresultMatrixに格納しています。

この例では、[[3, 5], [7, 9]]という結果が得られるでしょう。

○サンプルコード8:2次元配列を使った行列の転置

行列の転置とは、行と列を入れ替える操作を指します。

具体的には、2次元配列の要素[i][j]を[j][i]の位置に移動させることで行列の転置が実現できます。

ここでは、2×3行列を転置して3×2行列に変換するサンプルコードを紹介します。

var originalMatrix = [[1, 2, 3], [4, 5, 6]]
var transposedMatrix = Array(repeating: Array(repeating: 0, count: 2), count: 3)

for i in 0..<originalMatrix.count {
    for j in 0..<originalMatrix[i].count {
        transposedMatrix[j][i] = originalMatrix[i][j]
    }
}

print(transposedMatrix)

このコードでは、originalMatrixの行と列を入れ替えた結果をtransposedMatrixに格納しています。

この例を実行すると、[[1, 4], [2, 5], [3, 6]]という転置された2次元配列が得られるでしょう。

○サンプルコード9:2次元配列を使ったマップの作成

Swiftでの2次元配列の利用方法の一つとして、ゲームやアプリケーションでのマップの表現があります。

簡単に言えば、2次元配列を使うことで、座標を持つマップやフィールドのようなものを作成することができます。

ここでは、Swiftで2次元配列を使って簡単なマップを作成する方法を具体的なサンプルコードを交えて解説します。

このコードでは、2次元配列を使って5×5のマップを表しています。

この例では、0を空白とし、1を壁や障害物として表現しています。

// 2次元配列を使った5x5のマップを作成
let map: [[Int]] = [
    [1, 1, 1, 1, 1],
    [1, 0, 0, 0, 1],
    [1, 0, 1, 0, 1],
    [1, 0, 0, 0, 1],
    [1, 1, 1, 1, 1]
]

// マップを表示
for row in map {
    for column in row {
        print(column == 1 ? "壁" : "空", terminator: "")
    }
    print("")
}

このコードを実行すると、次のように5×5のマップがコンソールに表示されます。

壁と空の部分が正しく表示されることが確認できます。

壁壁壁壁壁
壁空空空壁
壁空壁空壁
壁空空空壁
壁壁壁壁壁

このように、2次元配列を利用することで、ゲームやアプリケーションのマップのような表現が簡単に実現できます。

さらに、このマップを基にキャラクターの移動や障害物の配置など、様々な拡張が可能です。

○サンプルコード10:2次元配列と関数を組み合わせる

2次元配列をさらに活用するために、関数と組み合わせる方法を見てみましょう。

関数を使用することで、2次元配列の操作や計算をより簡潔に、かつ効率的に行うことができます。

このコードでは、2次元配列を引数として受け取り、その合計値を返す関数を作成しています。

この例では、4×4の数値が格納された2次元配列を合計して、結果を表示しています。

// 2次元配列の合計値を計算する関数
func sumOf2DArray(array: [[Int]]) -> Int {
    var total = 0
    for row in array {
        for value in row {
            total += value
        }
    }
    return total
}

// 4x4の2次元配列
let numbers: [[Int]] = [
    [1, 2, 3, 4],
    [5, 6, 7, 8],
    [9, 10, 11, 12],
    [13, 14, 15, 16]
]

// 合計値を計算し表示
let result = sumOf2DArray(array: numbers)
print("2次元配列の合計値は\(result)です。")

このコードを実行すると、次のような結果が表示されます。

2次元配列の合計値は136です。

関数と2次元配列を組み合わせることで、繰り返しや計算の処理を効率的に、かつ見やすく実装することができます。

また、関数化することで再利用性が高まり、コードの品質や保守性も向上します。

○サンプルコード11:2次元配列を使ったゲームボードの作成

Swiftにおけるゲーム開発やアプリケーションの多くでは、2次元配列をゲームボードやマップとして活用することがあります。

今回は、シンプルなゲームボードの作成方法について解説します。

このコードでは、ゲームボードを模倣するための2次元配列を作成しています。

この例では、5×5のサイズのボードを生成し、その各セルにランダムに0(空きセル)または1(障害物)を配置します。

import Foundation

// 5x5のゲームボードを作成
var gameBoard: [[Int]] = Array(repeating: Array(repeating: 0, count: 5), count: 5)

// ランダムに障害物を配置
for i in 0..<gameBoard.count {
    for j in 0..<gameBoard[i].count {
        gameBoard[i][j] = Int.random(in: 0...1)
    }
}

// ゲームボードの表示
for row in gameBoard {
    print(row)
}

上記のコードを実行すると、5×5のゲームボードが生成され、その中にランダムな位置に障害物が配置されます。

例えば、次のような出力が得られることが考えられます。

[0, 1, 0, 0, 1]
[1, 0, 1, 0, 0]
[0, 0, 0, 1, 1]
[1, 0, 1, 0, 0]
[0, 0, 0, 0, 0]

このような形式の2次元配列は、ゲームのステージやマップの設計において非常に有用です。

障害物の位置やキャラクターの配置など、ゲームの状態を一目で理解することができます。

○サンプルコード12:2次元配列のデータをCSV形式で出力

データの保存や共有を容易にするため、2次元配列のデータをCSV形式で出力する方法も頻繁に利用されます。

特に、大量のデータを扱う場合や、他のプラットフォームやアプリケーションとの連携を考える際に、この方法は役立ちます。

このコードでは、2次元配列のデータをCSV形式で出力する方法を表しています。

この例では、先ほど作成したゲームボードのデータをCSVとして保存します。

// ゲームボードデータをCSV形式に変換
var csvData: String = ""

for row in gameBoard {
    csvData += row.map { String($0) }.joined(separator: ",") + "\n"
}

// CSVデータの表示
print(csvData)

上記のコードを実行すると、ゲームボードの2次元配列がCSV形式で変換され、出力されます。

例えば、以下のような出力が得られることが考えられます。

0,1,0,0,1
1,0,1,0,0
0,0,0,1,1
1,0,1,0,0
0,0,0,0,0

このCSV形式のデータは、ファイルとして保存したり、他のアプリケーションにインポートすることで、さまざまな用途に活用できます。

Swiftを用いたアプリケーション開発において、2次元配列のデータを効率的に取り扱うための方法の一つと言えるでしょう。

●注意点と対処法

Swiftで2次元配列を扱う際に注意すべきポイントと、それに対する対処法について詳しく見ていきましょう。

○2次元配列のサイズに関する注意

2次元配列は、実質的には配列の配列です。

そのため、外側の配列と内側の配列のサイズが異なることがあります。

例えば、外側の配列の要素数が3で、それぞれの内側の配列の要素数が2、3、4だった場合、均一な2次元配列とは言えません。

このコードでは、外側の配列と内側の配列のサイズが異なる2次元配列を作成しています。

この例では、外側の配列の要素数が3で、内側の配列の要素数がそれぞれ2、3、4となっています。

let twoDimArray = [[1,2],[3,4,5],[6,7,8,9]]
print(twoDimArray)

このコードを実行すると、[[1,2],[3,4,5],[6,7,8,9]]という出力が得られます。

このような2次元配列を扱う際、内側の配列のサイズを前提として処理を行うとエラーが発生する可能性があるため注意が必要です。

特に、配列の特定の位置にアクセスする際や、ループ処理を行う際には注意が必要です。

○型の不一致に起因するエラーの対処法

Swiftは静的型付け言語であるため、一度型を決定すると、その型の値のみを受け入れることができます。

したがって、2次元配列内で異なる型の要素を混在させることはできません。

このコードでは、Int型とString型の値を混在させて2次元配列を作成しようとしています。

この例では、[1,"apple"]という配列を作成しようとしてエラーが発生します。

//let mixedArray = [[1,2,3],["apple","orange"]] // エラーが発生

このようなケースでエラーを避けるためには、配列内のすべての要素が同じ型であることを確認する必要があります。

必要に応じて、適切な型変換を行うことで問題を解決できます。

○nilやOptionalと2次元配列の取り扱い

Swiftにおいて、nilは値が存在しないことを示す特別な値です。

Optionalは、値が存在するかもしれない、または存在しないかもしれないという意味を持つラッパー型です。

2次元配列内でOptionalを扱う際には、アンラップ(値の取り出し)に注意が必要です。

このコードでは、Optionalを含む2次元配列を作成し、その要素をアンラップしています。

この例では、[1,nil,3]という配列の中のnilを取り扱っています。

let optionalArray: [[Int?]] = [[1,nil,3],[4,5,6]]
for innerArray in optionalArray {
    for item in innerArray {
        if let unwrappedItem = item {
            print(unwrappedItem)
        } else {
            print("Nil value found!")
        }
    }
}

このコードを実行すると、1, Nil value found!, 3, 4, 5, 6という順序で出力されます。

2次元配列内でOptionalを使用する際は、アンラップする前に値が存在するかどうかを確認するか、if letguard letを使用して安全にアンラップすることが推奨されます。

●2次元配列のカスタマイズ方法

Swiftでの2次元配列を使用する際に、標準的な操作だけでなく、より高度なカスタマイズが必要となる場面も多くあります。

ここでは、そのようなカスタマイズ方法をいくつかご紹介します。

○配列の拡張を利用したカスタマイズ

Swiftにおける配列は非常に柔軟で、その特性を生かして2次元配列のカスタマイズも可能です。

特に、拡張(Extension)を利用することで、2次元配列に新たな機能や操作を追加することができます。

このコードでは、2次元配列に新しいメソッド「printMatrix」を追加しています。

この例では、2次元配列の各要素を綺麗に出力するためのメソッドを追加しています。

extension Array where Element: Collection {
    func printMatrix() {
        for row in self {
            for item in row {
                print(item, terminator: "\t")
            }
            print("")
        }
    }
}

let matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
matrix.printMatrix()

このコードを実行すると、次のような出力が得られます。

1    2    3    
4    5    6    
7    8    9   

このように、拡張を利用すれば、2次元配列に特有の機能や操作を簡単に追加することができます。

○2次元配列のメモリ効率の最適化

2次元配列は、データを効率的に扱うための非常に強力なツールですが、大量のデータを扱う場合や頻繁に更新する場合など、メモリ効率が求められる場面もあります。

そのような場合には、メモリ効率を考慮したカスタマイズが必要となります。

例えば、ほとんどの要素が0であるような「疎な」2次元配列の場合、全ての要素を保持するのではなく、0以外の要素の位置とその値だけを保持する「疎行列」の形式でデータを保持することで、メモリ効率を大幅に向上させることができます。

このコードでは、疎行列を表現するためのデータ構造を作成し、その上で基本的な操作を行っています。

この例では、非0の要素の位置とその値をDictionaryで保持し、効率的に2次元配列を表現しています。

struct SparseMatrix {
    private var data: [Int: [Int: Int]] = [:]

    mutating func set(value: Int, row: Int, col: Int) {
        if data[row] == nil {
            data[row] = [:]
        }
        data[row]![col] = value
    }

    func get(row: Int, col: Int) -> Int {
        return data[row]?[col] ?? 0
    }
}

var sparse = SparseMatrix()
sparse.set(value: 5, row: 2, col: 3)
print(sparse.get(row: 2, col: 3))  // 出力は「5」になります。

この疎行列の形式を採用することで、非0の要素が少ない場合には、通常の2次元配列よりもメモリ効率の良いデータ構造を持つことができます。

まとめ

Swiftにおける2次元配列は、データを格子状に整理・管理する際に非常に便利なツールです。

本記事では、2次元配列の基本的な使い方から、さまざまな応用例、カスタマイズ方法に至るまでを、具体的なサンプルコードとともに詳細に解説しました。

これにより、読者の皆様は2次元配列の使い方の基本をしっかりと把握することができるでしょう。

特に、2次元配列のカスタマイズ方法では、配列の拡張を利用したカスタマイズや、メモリ効率の最適化についての詳しい解説を行いました。

これらの知識を活かせば、より効率的で高性能なプログラムの作成が可能となります。

また、2次元配列を使用する際の注意点や対処法についても触れましたので、実際にコーディングを行う際の参考としてもお役立ていただける内容となっています。

Swiftの2次元配列を用いることで、データの整理や操作が非常に簡単になります。

しかし、その使い方をしっかりと理解し、適切に使用することが大切です。

本記事が、Swiftでの2次元配列の活用に関する貴重なガイドとなれば幸いです。

継続的な学習と実践を通じて、Swiftの2次元配列を完璧にマスターしてください。