Swiftの辞書(Dictionaries)

辞書(Dictionaries)

辞書コレクション型(Dictionaries)は連想配列の一つで、要素を指定するkeyと要素自体(値)valueを一組としたコレクション型です。要素を指定する添字に任意の基本型を選べるので、コレクション型の自由度が配列(Arrays)に比べて格段に上がります。

辞書コレクション型(Dictionary)とは?

Swiftの辞書コレクション型(Dictionaries)は、いわゆる連想配列というタイプのコレクション型です。連想配列は添字(index)に整数以外の値を持てるコレクション型です。おおざっぱに言うと、Swiftの配列(Arrays)の添字である整数を任意の型に拡張したコレクション型になります。

[図解]配列と辞書の違い

上の図はArrayとDictionaryの違いを簡単に説明したものです。Arrayでは添字は整数ですから、上記のように値を入れた場合、添字と値(型の名前)の対応には特に意味はありません。

しかし、Dictionaryの場合、添字に任意の型を指定できます(上記の場合、型の英語名をStringで指定)。こうすると、値を取り出す際にユーザは直感的に指定ができて便利です。この添字と値の対応関係は、まさに「辞書」のようなものですね。もちろん、添字と値に対応を持たせるように名前をつけるのが重要になります。

辞書コレクション型の初期化

毎回「辞書コレクション型」と書くと長いので、以下「辞書型」とします。辞書型の初期化は、ArraysSetsと基本的には同じですが、初期化に辞書型リテラルを使います。

辞書型リテラル(Dictionary Literal)で初期化

辞書型リテラルは、各key-value対をコンマで分けます。

// 辞書型リテラル
[key1: value1, key2: value2, ...]

key-vaule対はkey: valueのように、コロン:で分けます。

Swiftの基本型を文字列としてkeyに持ち、その日本語名を値に持つような辞書型を考えてみます。例えば、"String": "文字列型"

// 辞書コレクション型の例
var swiftTypes: Dictionary<String, String> = ["Int": "整数型", "Duoble": "浮動小数点型", "String": "文字列型"]
// 省略形 1
var swiftTypes: [String: String] = ["Int": "整数型", "Duoble": "浮動小数点型", "String": "文字列型"]
// 省略形 2
var swiftTypes: Dictionary = ["Int": "整数型", "Duoble": "浮動小数点型", "String": "文字列型"]
// 省略形 3
var swiftTypes = ["Int": "整数型", "Duoble": "浮動小数点型", "String": "文字列型"]

正確に書けば一番上の例のような表記になりますが、2番目以降のような省エネ宣言も可能です。3番目と4番目の初期化は、これまで何度も出てきたSwiftの型推論を使った書き方です。

また、Dictionaryではkeyの重複は不可能です(同じkeyを持てない)。valueは同じでも構いません。

// 同じkeyはダメ
var swiftTypes = ["Int": "整数型", "Int": "integer"]
//エラー:fatal error: Dictionary literal contains duplicate keys

// valueは同じでも大丈夫
var color = ["赤": "ff0000", "red": "ff0000", "あか": "ff0000"]

空のDictionary作成

ArraysやSetsと同様、空のDictionaryを作ることが可能です。

// [String: Int]型の空のDictionaryを作成
var theme = [String: Int]()

値の代入にはArraysと同様にサブスクリプト構文(subscript syntax)が使えます。今、DictionaryのthemeはkeyとしてString、値にはIntを取りますので、例えば

// [String: Int]型のDictionaryに値を代入
theme["twentyFifteen"] = 2015

という具合にkey-value対を指定できます。

また空の辞書型リテラル[:]を代入することもできます。

// 空の辞書型リテラルを代入
theme = [:]
print("\(theme.count)") // 0
// Dictionaryの要素数は0。型[String: Int]は保持。

少し複雑ですが、空の辞書型リテラルを使った初期化方法もあります。

// Dictionaryの初期化
var theme1: Dictionary<String, Int> = [:]
var theme2: [String: Int] = [:]

辞書型要素へのアクセス、変更

ここでは主にサブスクリプト構文(subscript syntax)を使った辞書型要素へのアクセスと、要素の変更に関して説明します。

辞書型要素へのアクセス

要素へアクセスしたい時は、サブスクリプト構文でkeyを指定します。

// Dictionaryの要素へアクセス
print("\(swiftTypes["Int"])")
// "Optional("整数型")"と表示

サンプルコードの結果から分かりますが、Dictionaryでは単にサブスクリプトでアクセスしようとするとオプショナル型(Optionals)になります。これは、存在しないkeyにアクセスした場合の実行エラーを防ぐためだと思います。

何が言いたいかと言うと、Optionalsで包んでおけば、存在しないkeyを指定した場合nilにできる、ということです。

// Dictionaryの要素へアクセス、存在しないkey
print("\(swiftTypes["UInt"])")
// "nil"と表示

ただ、nilなので、取り扱い次第ではやはり実行エラーを起こしてしまうかもしれません。nilに関してはこちらのページを参照下さい。

したがって、OptionalsをはずすためにOptional Bindingなどを使って要素にアクセスします。

// Optional Bindingでアクセス
if let typeName = swiftTypes["Int"] {
  print("Intは\(typeName)です。")
} else {
  print("Intはswift型Dictionaryには入っていません。")
}
// "Intは整数型です。"と表示
keyが確実に指定出来る場合なら、Forced Unwrappingでも良いかもしれませんね。

辞書型要素の追加と変更

Dictionaryへ要素を追加する場合、

// Dictionaryへ要素を追加
swiftTypes["Character"] = "文字型"
swiftTypes["Short"] = "整数型"

のように、subscript syntaxで新しいkeyを指定して、値を代入することができます。

既存の値を変更することも可能です。

// Dictionaryの値変更
swiftTypes["Short"] = "短整数型"

また、指定したkeyの値にnilを代入することで、既存のkey-value対を削除することができます。

// Dictionaryの既存要素を削除
swiftTypes["Short"] = nil

確認してみましょう。

// Dictionaryの各要素を表示
for (type, japaneseExpression) in swiftTypes {
  print("型:\(type) (\(japaneseExpression))")
}
// 型:Duoble (浮動小数点型)
// 型:String (文字列型)
// 型:Int (整数型)
// 型:Character (文字型)

確かに、一度代入したShort-短整数型対は、値にnilを代入したことで削除されていることが分かります。蛇足ですが、上記の例のように、Dictionaryのkey-value対を一度に取り出す際にTuplesが使えます

上記の例では、key-value対をtupleで取り出しましたが、それぞれを単独で取得することも可能です。

// Dictionaryのkeyを取り出す
for type in swiftTypes.keys {
  print("\(type)")
}
// Duoble
// String
// Int
// Character

// Dictionaryの値を取り出す
for value in swiftTypes.values {
  print("\(value)")
}
// 浮動小数点型
// 文字列型
// 整数型
// 文字型

さらに、keys, valuesで取り出した値を配列(Arrays)に格納することも可能です。

// Dictionaryのkey、valueをArraysに格納
let type = [String](swiftTypes.keys)
let japaneseExpression = [String](swiftTypes.values)
// typeとjapaneseExpressionはStringの値を持つArrays

まとめ

  • 辞書コレクション型(Dictionary)は連想配列。[添字、値]を一組の要素とするコレクション型。
  • 添字(key)には整数以外の任意の基本型(例えばString)が使えるが、keyの重複は不可。
  • Dictionaryの初期化には辞書型リテラル(dictionary literal)を使う。
  • Subscript syntaxを使ってDictionaryにアクセスする際、戻り値はOptionalsになる
  • Dictionaryの添字や値は、別々にArraysとして取り出すことができる