Swiftで学ぶ!多次元配列の使い方10選 – JPSM

Swiftで学ぶ!多次元配列の使い方10選

Swift言語での多次元配列の操作と実例を表すイメージSwift

 

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

このサービスは複数のSSPによる協力の下、運営されています。

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

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

また、理解しにくい説明や難しい問題に躓いても、JPSMがプログラミングの解説に特化してオリジナルにチューニングした画面右下のAIアシスタントに質問していだければ、特殊な問題でも指示に従い解決できるように作ってあります。

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

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

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

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

はじめに

Swiftのプログラミング言語を学ぶ中で、多次元配列の扱いはとても重要です。

多次元配列とは、名前の通り、配列の中にさらに配列が入っているデータ構造のことを指します。

この記事を読めば、Swiftでの多次元配列の扱い方を10通りの方法で学べるようになります。

とはいえ、多次元配列は初心者には少し難しそうに思えるかもしれません。しかし、基本的な考え方を理解すれば、それほど複雑なものではありません。

今回は、初心者の方でもわかるように、基本的な使い方から応用まで、Swiftにおける多次元配列の使い方を詳しく解説していきます。

それでは、Swiftと多次元配列の魅力について少し掘り下げてみましょう。

●Swiftと多次元配列の基礎知識

○Swiftとは?

Swiftは、Appleが開発したプログラミング言語で、iOSやmacOS、watchOSなどのアプリケーション開発に広く使用されています。

CやObjective-Cとは異なり、Swiftは初心者にも扱いやすいシンタックスを持ち、パフォーマンスも高いという特徴があります。

そのため、アプリ開発を始める方々にとって、非常に魅力的な言語と言えるでしょう。

○多次元配列の特徴とメリット

多次元配列は、2次元、3次元といった形で、配列の中にさらに配列が含まれているデータ構造を指します。

たとえば、学校の成績表やゲームのマップ情報など、実際の世界での多様な情報を効果的に表現するのに役立ちます。

一般的な1次元の配列と比較して、多次元配列のメリットは次の通りです。

  1. データの階層構造を自然に表現できる。
  2. 行列やテーブルデータのような情報を効率的に管理できる。
  3. ゲームのマップや3Dグラフィックスなど、複雑なデータ構造を扱うのに適している。

●多次元配列の作り方

Swiftにおける多次元配列の作成は非常にシンプルです。

一般的に、配列は[]を使用して定義されますが、多次元配列の場合は、この[]を重ねることで定義が可能です。

○基本的な定義方法

多次元配列は、配列の中にさらに配列を持つデータ構造です。

たとえば、2次元配列は、表やマトリックスのような形でデータを保持することができます。

2次元配列の基本的な定義は次のようになります。

// 整数の2次元配列を定義
var matrix: [[Int]] = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]

このコードでは、整数を要素とする3×3の2次元配列を定義しています。

matrix[0][0]で1、matrix[1][2]で6というようにアクセスできます。

3次元配列やそれ以上も、同じように[]を増やして定義することができます。

○初期化の方法

Swiftでは、配列の初期化はいくつかの方法で行えます。

特に、多次元配列の場合は、適切な初期化方法を知っておくと非常に便利です。

  1. サイズと初期値を指定して初期化
// 3x3の2次元配列を0で初期化
var initializedMatrix = Array(repeating: Array(repeating: 0, count: 3), count: 3)

このコードでは、0で初期化された3×3の2次元配列が生成されます。

  1. Arrayのコンストラクタを使用して初期化
var anotherMatrix: [[Int]] = Array([[1,2,3], [4,5,6], [7,8,9]])

この方法も上記の定義方法とほとんど変わりませんが、Arrayのコンストラクタを使うことで、型推論がやや明確になります。

●多次元配列の詳細な使い方

Swiftにおける多次元配列は非常に柔軟性があり、様々な操作が可能です。

ここでは、その詳細な使い方をサンプルコードと共に解説します。

○サンプルコード1:2次元配列のデータアクセス

2次元配列の要素へのアクセスは、インデックスを2つ使用して行います。

下記のサンプルコードでは、2次元配列の特定の要素にアクセスし、その値を変更する方法を表しています。

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

// matrix[1][1]は5という値になっています
matrix[1][1] = 10
// このコードを実行すると、matrix[1][1]は10という値に変更されます

このコードでは、2次元配列の2行2列目の要素(インデックスとしては[1][1])を10に変更しています。

○サンプルコード2:要素の追加と削除

Swiftの配列は動的にサイズが変更可能です。

これは多次元配列にも当てはまります。

下記のサンプルコードでは、2次元配列に新しい行を追加し、またその行を削除する方法を表しています。

var numbers: [[Int]] = [[1, 2, 3], [4, 5, 6]]

// 新しい行を追加
numbers.append([7, 8, 9])

// このコードを実行すると、numbersは[[1, 2, 3], [4, 5, 6], [7, 8, 9]]という値になります。

// 最後の行を削除
numbers.removeLast()

// このコードを実行すると、numbersは再び[[1, 2, 3], [4, 5, 6]]という値に戻ります。

このコードでは、初めに2×3の2次元配列を作成し、その後新しい行を追加して3×3の2次元配列にしています。

そして、最後にその追加した行を削除して元の2×3の2次元配列に戻しています。

○サンプルコード3:for文を使ったデータの取り出し

Swiftの多次元配列は、一次元配列と同じくfor文を使用してデータを取り出すことができます。

特に、ネストされたfor文を利用することで、多次元配列のすべての要素を効率的に取り出すことが可能です。

下記のサンプルコードは、2次元配列の各要素をネストされたfor文で取り出し、コンソールに表示する例を表しています。

let array2D: [[Int]] = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]

for row in array2D {
    for element in row {
        print(element)
    }
}
// このコードを実行すると、1から9までの数字が順番にコンソールに表示されます。

このコードでは、外側のfor文で2次元配列の各行(配列)を取り出し、内側のfor文でその行の各要素を取り出して表示しています。

この結果、1から9までの数字が順に表示されます。

○サンプルコード4:多次元配列のサイズ取得

多次元配列のサイズ、すなわち行数や列数を取得するには、配列のcountプロパティを使用します。

下記のサンプルコードでは、2次元配列の行数と、最初の行の列数を取得しています。

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

let numberOfRows = matrix.count
let numberOfColumns = matrix[0].count

// numberOfRowsには3が、numberOfColumnsには3が代入されます。

このコードでは、matrixという2次元配列の行数をnumberOfRowsに、最初の行の列数をnumberOfColumnsに代入しています。

そのため、numberOfRowsには3が、numberOfColumnsにも3が代入されます。

●多次元配列の応用例

Swiftの多次元配列は、基本的な操作だけでなく、さまざまな応用例でも大活躍します。

ここでは、多次元配列を使用した実践的な応用例をいくつか紹介します。

○サンプルコード5:2次元配列を用いた行列の計算

数学における行列の計算は、2次元配列を使用することでSwiftでも簡単に実装することができます。

下記のサンプルコードは、2つの行列(2次元配列)の加算を行う例を表しています。

let matrixA: [[Int]] = [
    [1, 2],
    [3, 4]
]
let matrixB: [[Int]] = [
    [2, 3],
    [4, 5]
]
var resultMatrix: [[Int]] = Array(repeating: Array(repeating: 0, count: 2), count: 2)

for i in 0..<2 {
    for j in 0..<2 {
        resultMatrix[i][j] = matrixA[i][j] + matrixB[i][j]
    }
}
// resultMatrixは、[[3, 5], [7, 9]]となります。

このコードでは、matrixAmatrixBという2つの2×2行列を定義し、それらの行列の各要素を加算してresultMatrixに格納しています。

結果として、resultMatrixには加算後の行列、すなわち[[3, 5], [7, 9]]が格納されます。

○サンプルコード6:3次元配列を使った3Dデータの表現

3次元のデータ、例えば立体の座標データなどを表現するために、3次元配列を使用することができます。

ここでは、3次元空間上の点の集合を3次元配列で表現する例を紹介します。

let spacePoints: [[[Int]]] = [
    [[0, 0, 0], [1, 0, 0]],
    [[0, 1, 0], [1, 1, 0]],
    [[0, 0, 1], [1, 0, 1]]
]

for layer in spacePoints {
    for row in layer {
        for point in row {
            print("点の座標: (\(point[0]), \(point[1]), \(point[2]))")
        }
    }
}
// このコードを実行すると、各点の3次元座標がコンソールに表示されます。

このコードでは、3次元空間上の点の集合をspacePointsという3次元配列で表現しています。

その後、ネストされたfor文を使用して、各点の座標をコンソールに表示しています。

3次元配列を使用することで、立体的なデータの表現や操作が非常に簡単になります。

○サンプルコード7:多次元配列と関数の組み合わせ

Swiftの多次元配列と関数を組み合わせることで、データの操作や変換をより効率的に行うことができます。

関数を使用することで、多次元配列の各要素を繰り返し処理したり、特定の条件に基づいて要素を変更したりする際のコードの冗長性を減少させることができます。

例として、2次元の整数配列のすべての要素を2倍する関数を作成してみましょう。

func doubleElements(of matrix: [[Int]]) -> [[Int]] {
    var doubledMatrix: [[Int]] = []
    for row in matrix {
        var newRow: [Int] = []
        for element in row {
            newRow.append(element * 2)
        }
        doubledMatrix.append(newRow)
    }
    return doubledMatrix
}

let sampleMatrix: [[Int]] = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]

let doubledResult = doubleElements(of: sampleMatrix)
// doubledResultには、[[2, 4, 6], [8, 10, 12], [14, 16, 18]]が格納されます。

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

この関数は2次元の整数配列を引数として受け取り、そのすべての要素を2倍した新しい2次元配列を返します。

関数を使用することで、配列の要素を2倍する処理を一箇所に集約することができ、他の多次元配列にも同様の操作を簡単に適用できます。

○サンプルコード8:filterやmapを利用した操作

Swiftには、配列やコレクションに対する操作を行うための高階関数が用意されています。

その中で特によく使用されるのが、filtermapなどの関数です。

これらの関数を多次元配列に適用することで、効率的なデータ操作を実現できます。

下記のサンプルコードでは、2次元配列の各要素から偶数のみを抽出する例を表しています。

let numbersMatrix: [[Int]] = [
    [1, 2, 3, 4],
    [5, 6, 7, 8],
    [9, 10, 11, 12]
]

let evenNumbersMatrix = numbersMatrix.map { row -> [Int] in
    return row.filter { $0 % 2 == 0 }
}
// evenNumbersMatrixには、[[2, 4], [6, 8], [10, 12]]が格納されます。

このコードでは、map関数を使用して2次元配列numbersMatrixの各行を操作しています。

その中でfilter関数を使用し、各行の要素から偶数のみを抽出して新しい2次元配列evenNumbersMatrixを作成しています。

mapfilterを使用することで、多次元配列の操作を簡潔に記述することができます。

○サンプルコード9:JSON形式のデータとしての利用

JSON(JavaScript Object Notation)は、データ交換フォーマットの一つとして広く使われています。

Swiftでは、JSONEncoderJSONDecoderを使って、構造体やクラスをJSON形式のデータとしてエンコードしたり、逆にJSONデータをデコードしてSwiftのオブジェクトに変換することができます。

この機能を利用することで、多次元配列もJSON形式のデータとして保存や通信に利用することが可能です。

まず、Swiftの多次元配列をJSON形式の文字列に変換する方法を紹介します。

import Foundation

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

if let jsonData = try? JSONSerialization.data(withJSONObject: matrix, options: []) {
    if let jsonString = String(data: jsonData, encoding: .utf8) {
        print(jsonString)
        // 出力は "[[1,2,3],[4,5,6],[7,8,9]]" となります。
    }
}

このコードでは、Swiftの標準ライブラリFoundationJSONSerializationクラスを使用して、多次元配列matrixをJSON形式のデータに変換しています。

変換されたデータは、UTF-8の文字列として出力されます。

次に、JSON形式の文字列をSwiftの多次元配列に変換する方法を紹介します。

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

if let data = jsonString.data(using: .utf8) {
    if let decodedMatrix = try? JSONSerialization.jsonObject(with: data, options: []) as? [[Int]] {
        print(decodedMatrix)
        // 出力は [[1, 2, 3], [4, 5, 6], [7, 8, 9]] となります。
    }
}

こちらのコードでは、JSONSerializationクラスのjsonObject(with:options:)メソッドを使用して、JSON形式の文字列jsonStringをSwiftの多次元配列にデコードしています。

○サンプルコード10:多次元配列を使ったゲームのボード表現

ゲーム開発では、ボードゲームの盤面や迷路、地形などを多次元配列として表現することが一般的です。

多次元配列を使用することで、ゲーム内の各セルや位置にアクセスして、情報を更新したり取得したりすることが容易になります。

ここでは、3×3のボードゲームの盤面を表現する簡単な例を紹介します。

var board: [[String]] = [
    ["-", "-", "-"],
    ["-", "-", "-"],
    ["-", "-", "-"]
]

// プレイヤーXが(1,1)の位置に駒を置く
board[1][1] = "X"

このコードでは、3×3のボードゲームの盤面をboardという2次元配列で表現しています。

最初、すべてのセルは”-“(空きマス)で初期化されています。

その後、プレイヤーXが(1,1)の位置に駒を置く操作をシミュレートしています。

●多次元配列の注意点と対処法

多次元配列は、データの構造や操作を効率的に行うために非常に便利ですが、適切に使用しないと思わぬエラーや問題に直面することがあります。

ここでは、Swiftで多次元配列を使用する際の主要な注意点と、それに対する対処法を紹介します。

○データ型の一貫性

多次元配列を使用する際の最も基本的な注意点は、配列内のすべての要素が同じデータ型であることを確認することです。

型が異なる要素を混在させると、エラーが発生する可能性があります。

例えば、次のようなコードはエラーとなります。

var invalidArray: [[Any]] = [
    [1, "Apple", true],
    [2, "Banana", false]
]

このコードは、整数、文字列、ブール値が混在した多次元配列を定義しようとしています。

Swiftは静的型付け言語であるため、このような混在は許容されていません。

対処法として、配列内の要素のデータ型を明示的に指定して、型の混在を避ける必要があります。

もし異なる型のデータを格納する必要がある場合は、構造体やクラスを定義して使用することを検討してください。

○メモリの効率的な使用

多次元配列は、多くのデータを格納することができますが、その分メモリの消費量も増加します。

特に大量のデータを持つ多次元配列を扱う場合、メモリ効率を意識することが重要です。

例えば、次のコードは、100×100の2次元配列を作成しています。

var largeArray = Array(repeating: Array(repeating: 0, count: 100), count: 100)

このような大きな配列を頻繁に作成・破棄すると、メモリの断片化やパフォーマンスの低下が生じる可能性があります。

対処法として、不要になった配列は速やかに破棄する、または配列のサイズを適切に管理して、メモリを効率的に使用するよう努力することが必要です。

○配列の境界を超えるアクセス

多次元配列の要素にアクセスする際、配列の境界を超えてアクセスしようとすると、実行時エラーが発生します。

このようなエラーは、アプリケーションのクラッシュを引き起こすため、特に注意が必要です。

例えば、次のコードは、3×3の2次元配列の要素にアクセスしようとしていますが、存在しない4行目の要素にアクセスしようとしているためエラーとなります。

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

print(matrix[3][0])  // 実行時エラー

対処法として、配列のサイズを確認してから要素にアクセスするか、配列のサブスクリプトをオーバーライドして範囲外のインデックスへのアクセスを安全にハンドリングする方法が考えられます。

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

Swiftでの多次元配列は、デフォルトのままでも非常に強力ですが、プロジェクトの要件に応じてカスタマイズすることで、さらに便利に使えるようになります。

ここでは、多次元配列をカスタマイズする方法として、独自のデータ型の組み込み方や、拡張メソッドを利用した機能の追加方法について紹介します。

○独自のデータ型を組み込む方法

Swiftでは、構造体やクラスを使用して独自のデータ型を定義することができます。

多次元配列に独自のデータ型を組み込むことで、配列内の要素に対して簡単にアクセスしたり、操作したりすることが可能となります。

例として、店舗の情報を持つデータ型を定義し、それを2次元配列で管理する方法を考えてみましょう。

// 店舗情報を保持する構造体を定義
struct Shop {
    var name: String
    var address: String
    var sales: Int
}

// 2次元配列に店舗情報を格納
var shopLists: [[Shop]] = [
    [Shop(name: "店舗A1", address: "住所A1", sales: 100),
     Shop(name: "店舗A2", address: "住所A2", sales: 200)],

    [Shop(name: "店舗B1", address: "住所B1", sales: 150),
     Shop(name: "店舗B2", address: "住所B2", sales: 250)]
]

// アクセスの例
let salesA1 = shopLists[0][0].sales  // 100が取得できる

このコードでは、店舗の名前、住所、売上を保持するShopという構造体を定義しています。

その後、このShopを要素として持つ2次元配列shopListsを定義し、実際に店舗情報を格納しています。

このようにすることで、店舗の情報を一元的に管理しやすくなります。

○拡張メソッドを利用した機能追加

Swiftでは、既存の型に新しいメソッドやプロパティを追加することができる拡張(Extension)という機能が提供されています。

これを利用して、多次元配列に特定の操作を簡単に行うためのメソッドを追加することができます。

例として、2次元配列の全要素の合計を計算するメソッドを追加してみましょう。

extension Array where Element == [Int] {
    func totalSum() -> Int {
        return self.flatMap { $0 }.reduce(0, +)
    }
}

// 使用例
let numbers: [[Int]] = [
    [1, 2, 3],
    [4, 5, 6]
]

let sum = numbers.totalSum()  // 合計21が得られる

このコードでは、Array型にtotalSumという新しいメソッドを追加しています。

このメソッドは、2次元配列の全要素の合計値を計算して返します。

拡張を利用することで、多次元配列をより直感的に操作することが可能となります。

まとめ

Swiftにおける多次元配列は、データの階層的な構造を表現するのに非常に役立つツールです。

この記事を通じて、多次元配列の基本的な定義から、より高度な操作やカスタマイズ方法について解説しました。

初心者の方から上級者まで、Swiftの多次元配列を効果的に活用するための知識や技術を深めることができる内容となっています。

特に、カスタマイズ方法を駆使することで、Swiftの多次元配列をさらにパワフルに使いこなせることを確認できました。

プログラミングの現場では、データの構造や要件に応じて、多次元配列を適切に利用することが求められます。

今回学んだ内容を元に、Swiftでの多次元配列の活用方法をぜひ実践してみてください。

日々のコーディング作業が、よりスムーズで効果的になることを期待しています。