【Swift】コレクションについて〜配列〜

#コレクション とは

コレクションとは値の集まりを意味します。

swiftには、様々なコレクションがありますので、
今回はその中の一つである配列について記述します。

##Array\<Element>型
Array\<Element>型が配列を表す型になります。

Elementの部分はOptional\<Wrapped>型と同じプレースホルダ型になっていますので、
Array\<Int>型やArray\<String>型のように使用します。

Array\<> のように山括弧(\<>)で囲っていますが、
実際に記述する時は、[ ] のようにブラケット(角括弧)で囲います。


##配列リテラル

配列リテラルとは、カンマ区切りの値をブラケットで括った形式で表現されたものです。
このようにして配列を宣言します。

```swift

let a = [1, 2, 3]
let b = ["a", "b", "c"]
```

配列aには、1, 2, 3 という三つの値が格納されていることになります。

また、Int型やString型と同様に、型推論の機能も備わっております。
配列は、Array\<Element>型のプレースホルダ型Elementを型推論します。

今回のように、配列aはInt型の要素しか持っていないので**[Int]型**と推論されます。
この時に注意しなければならないのは、Int型ではなく[Int]型だということです。

```swift

let a = [1, 2, 3]   // [Int]型
let b = ["a","b","c"]   // [String]型
```

配列の中に値が一つでも入っていれば型推論ができますが、
空の状態(一つも値が入っていない)の場合は型推論ができません。

したがって空の配列を作る場合は明示的に宣言してあげなければなりません。

```swift

let a: [Int] = []   // [Int]型の空配列
let b: [String] = []   // [String]型の空配列
```

`[1, "a"]`のように配列が複数の型を含む場合も、型推論ができなくなります。
このような場合も同様に明示的に型推論してあげなければなりません。

```swift

let a = [1, "a"]   // コンパイルエラー
```
エラー内容：`Heterogeneous collection literal could only be inferred to '[Any]'; add explicit type annotation if this is intentional`
和訳：異種コレクションリテラルは、「[Any]」にのみ推測できます。 これが意図的なものである場合は、明示的な型注釈を追加します

[Int]型か[String]型かわからないので、
両方の継承関係にある[Any]型を明示的に宣言しなければなりません。

```swift

let a: [Any] = [1, "a"]
```

###要素にできる型
Array\<Element>型は、Element型の値を要素にすることが可能です。

Array\<Int>型つまり[Int]型の場合は、Int型を要素にすることができ、
Array\<String>型つまり[String]型の場合は、String型を要素にすることができます。

**Element型にはどのような型でも当てはめることができます。**

中でも面白いなと思ったのは、**二次元配列**です。
二次元配列は、配列の中に配列を入れることにより作ることができます。

```swift

let a = [[1, 2, 3], [4, 5, 6]]   // Array<Array<Int>>型
```

`Array<Array<Int>>型`つまり`[[Int]]型`ということですね。
こんなのいつ使う時が来るのでしょうか・・・。

学ぶことが多すぎて大変です(笑)

##Array\<Element>型の操作

Array\<Element>型の要素にアクセス方法は、サブスクリプトというものを使用します。

サブスクリプトとは、配列にインデックス(添字)を与え、
そのインデックスの位置に該当する要素の取得や書き換えを行う機能です。

記述のしかたは`配列名[インデックス]`といった感じです。

ここで一つ注意なのですが、配列のインデックスは0から始まります。
つまり我々の思う配列の１番目はインデックスでいうと０番目になります。

```swift

let strings = ["aa","bb","cc"]   // インデックスは、0, 1, 2 
let a = strings[0]   // aa
let b = strings[1]   // bb
let c = strings[2]   // cc
let d = strings[3]   // [3]は範囲外なので実行時エラー
```

エラー内容：`Fatal error: Index out of range`
和訳：致命的なエラー：インデックスが範囲外

配列の操作を行う場合は、インデックスの値に気をつけてください！

##配列の更新、追加、結合、削除

配列には様々な機能が備わっております。

すでに宣言されている配列の要素を更新するには、
更新したい要素のインデックスを指定し、代入演算子(=)を用いて更新します。

配列をいじる時はletではなくvarで宣言しないとコンパイルエラーが出るので注意。

```swift

var strings = ["aa","bb","cc"]
strings[1] = "xx"
strings   // ["aa","xx","cc"]
```

***
末尾に新たに要素を加えたい場合は、`append(_:)`メソッドを使用します。

Array\<Element>型のappend(_:)メソッドは、引数にElement型の値を入れます。
Array\<Int>型の場合は、append(Int型)ということになります。

```swift
var integers = [1, 2, 3]
integers.append(4)   // [1, 2, 3, 4]

var strings = ["aa","bb","cc"]   // Array<String>型
strings.append(1)   // Int型を入れてしまいコンパイルエラー
```

***
任意の場所に要素を追加したい場合は、`insert(_:at:)`メソッドを使用します。

insert(_: at:)メソッドは引数を二つ指定しています。
`insert(Element型, at: Int型)`のように引数を渡します。
`at: Int型`の部分には追加する位置を記載します。

```swift
var integers = [1, 3, 4]
integers.insert(2, at: 1)   // [1, 2, 3, 4]
```
***
同じ型の配列を一つのArrar\<Element>型にするには、`+演算子`を使用します。
当たり前ですが、型の違うものどうしを足すことはできません。

```swift
let integers1 = [1, 2, 3]   // [Int]型
let integers2 = [4, 5, 6]   // [Int]型
integers1 + integers2   // [1, 2, 3, 4, 5, 6]
```
***
要素の削除を行うメソッドは3つあり、
任意のインデックスの要素を削除する`remove(at:)`メソッド
最後の要素を削除する`removeLast()`メソッド
全ての要素を削除する`removeAll()`メソッドが存在します。

```swift

var integers = [1, 2, 3, 4, 5]

integers.remove(at: 3)   // [1, 2, 3, 5]   
integers.removeLast()   // [1, 2, 3]
integers.romoveAll()   // []
```

配列は必須の知識になってきますので、絶対に覚えておきましょう！

以上、最後までご覧いただきありがとうございました。