この記事ではSwiftの基本ある、辞書についての基本事項を解説していきます。
プログラミングが初心者も、他の言語をやっていてSwiftは初心者という人にもわかるように説明していきたいと思います。
サンプルコードも交えながら説明していきますので、Playgroundを使って実際に手を動かしながら行えると効率よく学習できるかなと思います。
Dictionary<Key, Value>型とは
Dictionary<Key, Value>型は辞書を表します。
辞書というのは、データの集まりをまとめて格納するデータ構造であるコレクションの1つで、キーと値のペアを持ちます。
Swiftで主要なコレクションは配列 (Array)、集合 (Set)、辞書 (Dictionary) の3つがあります。
Dictionary<Key, Value>型のKeyとValueの部分は、実際に使うときには具体的な型で置き換えて、Dictionary<String, Int>型のようにします。
辞書の宣言方法
Dioctionary<Key, Value>型は以下のようにキーと値を:で分けて、[]で囲みます。
let dictionay1: Dictionary<String, Int> = ["key1": 1, "key2": 2]
let dictionay2: Dictionary<String, String> = ["key1": "a", "key2": "b"]
上記の例では、Dictionary<String, Int>やDictionary<String, String>と記述しましたが、[String: Int]や[String: String]と書くこともできます。
実際に使うときは[String: Int]や[String: String]というように書くほうが一般的です。
このように、すでに定義されている構文をより簡単に読み書きできるように導入されている構文をシンタックスシュガーといいます。
let dictionay1: [String: Int] = ["key1": 1, "key2": 2]
let dictionay2: [String: String] = ["key1": "a", "key2": "b"]
2種類の表現が同じ意味を表す表現というのをわかっていないと、見たときに混乱してしまうのでしっかり押さえておきましょう。
辞書のルール
辞書はキーと値がペアになっていて、キーをもとに値にアクセスする形式なので、キーは他のものと被ってはいけません。
let dictionary: [String: Int] = ["key": 1, "key": 2] //実行時エラー
値に関しては、他のものと重複しても大丈夫です。
let dictionary: [String: Int] = ["key1": 1, "key2": 1]
キーも値も、異なる型を入れることはできません。
let dictionary1: [String: Int] = ["key": 1, 1: 1] //コンパイルエラー
let dictionary2: [String: Int] = ["key1": 1, "key2": "1"] //コンパイルエラー
型推論
辞書の要素が推論可能な場合、型アノテーションを省略することができます。
以下の例はキーがString型で、値はInt型なので[String: Int]型と推論されます。
let dictionay = ["key1": 1, "key2": 2] //[String: Int]型
型アノテーションとはlet b: [String: Int]の: [String: Int]の部分で型を明示的にする際に使用します。
要素が空の辞書は[:]と表します。
要素が空の場合には型アノテーションを付けて、型を明示する必要があります。
let a = [:] //コンパイルエラー
let b: [String: Int] = [:]
キーと値に使える型
Dictionary<Key, Value>型は定義を見てみると、
struct Dictionary<Key, Value> where Key: Hashable
となっています。
どういうことかというとKeyに関してはHashableプロトコルに準拠したものに制限されます。
プロトコルに関しては、後日別で記事にまとめるので、ここでは軽く触れるだけにします。
簡単にまとめると、Keyは一意でないといけないので、他とかぶっていないかを計算するためにハッシュ値というものを用いる必要があるので、Keyはハッシュ値を計算できるものでなければならないという成約があります。
String型やInt型はその条件を満たしているのでKeyとして使用可能です。
他にも条件を満たしている型はありますが、実際にKeyとしてよく使うのはその2つぐらいなので、それをおさえておけば問題ないと思います。
一方、Valueに関しては特に成約がないので、どんな型でも当てはめることができます。
[String: [Int]]型や[String: [String: Int]]型というようにすることもできます。
let a: [String: [Int]] = ["key": [1, 2, 3]]
let b: [String: [String: Int]] = ["key": ["key": 1]]
Dictionary<Key, Value>型の操作
ここからはDictionary<Key, Value>型の基本的な操作についてまとめていきます。
値へのアクセス方法
Dictionary<Key, Value>型の値にアクセスするには、以下のように[Key]の形式でアクセスします。
let dictionary: [String: Int] = ["key1": 1, "key2": 2]
dictionary["key1"] //1 (Optional<Int>型)
dictionary["key2"] //2 (Optional<Int>型)
dictionary["key3"] //nil
[インデックス]の部分をサブスクリプトといいます。
Dictionary<Key, Value>型では存在しないキーを指定したとしても、実行時エラーにはなりません。
そのかわりに、nilを含む可能性があるので、取り出した値はオプショナル型になります。
なので取り出した値を扱う場合はnilかどうかの場合分けをする必要があります。
オプショナル型に関してはこちらの記事で解説しています。
値の更新
辞書の要素の更新を行いたい場合は、以下のように更新したいキーを指定して、=で代入する形で書きます。
こちらは変数でないと実行できません。
var dictionary1: [String: Int] = ["key": 1]
dictionary1["key"] = 10
print(dictionary1) //["key": 10]
let dictionary2: [String: Int] = ["key": 1]
dictionary2["key"] = 10 //コンパイルエラー
値を追加
辞書に要素を追加する場合は、値の更新と同様に、追加したいキーを指定して値を=で代入する形で書きます。
こちらも、元の辞書を書き換える形になるものは変数でないと使えません。
var dictionary1: [String: Int] = ["key1": 1]
dictionary1["key2"] = 2
let dictionary2: [String: Int] = ["key1": 1]
dictionary2["key2"] = 2 //コンパイルエラー
値の削除
値を削除するには、削除したいキーを指定して、nilを代入することで可能です。
var dictionary1: [String: Int] = ["key": 1]
dictionary1["key"] = nil
let dictionary2: [String: Int] = ["key": 1]
dictionary2["key"] = nil //コンパイルエラー
値の更新、追加、削除のまとめ
Dictionary<Key, Value>型の値の更新、追加、削除のやり方を解説していきましたが、気づいた人もいるかも知れませんが、表記の仕方が全て同じになっています。
指定したキーが存在していれば更新、存在していなければ追加、nilを代入すれば削除となるのでしっかりおさえておきましょう。
- 指定した
キーが存在していれば更新 - 指定した
キーが存在していなければ追加 nilを代入すれば削除
まとめ
今回は、Dictionary<Key, Value>型に関してまとめていきました。
Dictionary<Key, Value>型はSwiftの基本事項なのでしっかり押さえておきましょう。
Swiftの入門記事に関してはこちらにまとめていますので参考にしてみてください。