Swift 文法その3 - 辞書 -

辞書は ["name": "taro", age: 10] のように複数の key: value の組み合わせを1つの変数に保存できます。

let で宣言するとKey/Valueの追加、削除、値の変更ができないので注意してください。また、辞書型は並び順が保証されません。ループして順番に処理しようとすると以下のように思ったような順番にはならないので注意しましょう(ループについてはまた後日ご紹介します)。

let dict = ["0": 0, "1": 1, "2": 2, "3": 3]
for (key, value) in dict {
    print(key) // "3", "2", "1"
}

宣言・初期化

var a: [String: Int] = [:]
var b = [String: Int]()
var c = [:] // データ型なしの空宣言はエラー
// データ型なし(型推論)var a = ["a": 100, "b": 200] // データ型あり var b: [String: Int] = ["a": 100, "b": 200]

また、init(grouping:by:) を使用すれば配列を指定して辞書を生成することができます。配列の要素はValueとなり、Keyはby: の部分で指定します。

// 文字数でグルーピング
let a = ["a", "ab", "bc"]
let b = Dictionary(grouping: a, by: { $0.count })
print(b) // [1: ["a"], 2: ["ab", "bc"]]

Hashableプロトコルに準拠してるものであればKeyとして使えるので、String型以外にもInt型だったり自作のオブジェクトを設定することも可能です(プロトコルについては後日紹介します)。Valueはどの型でも(Anyでも)OKです。

Key/Value の追加

var a: [String: Int] = [:]
a["a"] = 100

Valueの更新

var a = ["a": 100, "b": 200]a["a"] = 1000

default: を使用すると、指定したKeyがなかった時だけセットし、すでにある場合は上書きしないようにすることもできます。

let a = ["a": 100, "b": 300]
let b = a["b", default: 200]
let c = a["c", default: 200]
print(b) // 300
print(c) // 200

Keyの削除

var a: [String: Int] = ["a": 100, "b": 200]
a.removeValue(forKey: "a") // 特定のキーを削除
a.removeAll() // すべてのキーを削除

よく使うプロパティ

isEmpty: 空かどうか
count: Keyの数
keys: すべてのKeyを配列で取得
values: すべてのValueを配列で取得

よく使うメソッド

sorted: 辞書を並び替えます。

let a = ["c": 100, "a": 200, "b": 300]
let result = a.sorted() { $0.0 < $1.0 } // Keyの昇順
print(result) // [(key: "a", value: 200), (key: "b", value: 300), (key: "c", value: 100)]
let result = a.sorted() { $0.1 < $1.1 } // Valueの昇順
print(result) // [(key: "c", value: 100), (key: "a", value: 200), (key: "b", value: 300)]

sorted の返り値は並び順を保持するためにタプルで返ってきます(タプルについては後日紹介します)。

また、配列の並び替えの範疇になるかと思いますが、配列の要素が辞書型になっていて、その辞書の特定のKeyのValueでソートする場合の例もご紹介しておきます。

let arr = [["a": 1, "b": 2], ["a": 2, "b": 3], ["a": 3, "b": 4]]
let sortedArr = (arr as NSArray).sortedArray(using: [NSSortDescriptor(key: "a", ascending: false)]) as! [[String: Any]]
print(sortedArr) // [["b": 4, "a": 3], ["a": 2, "b": 3], ["a": 1, "b": 2]]

要素内の辞書のKey/Valueは並び順が保証されていないので順番がばらばらになっていますが、要素の順番自体は指定したKey(ここでは"a")の降順になっています。使う機会はあまりないと思うので、ここではこういうものとだけ認識していただければと思います。

filter: 条件に一致する Key/Value を返します。

let result =  ["a": 100, "b": 200].filter { $0.value > 100 } // Valueが100以上
print(result) // ["b": 200]

mapValues: Valueだけをmapで処理を加え、Keyはそのままの状態で新しい辞書を返します。

let a = ["a": 100, "b": 200].mapValues { $0 * 2 }
print(a) // ["a": 200, "b": 400]

merge: 辞書同士を結合します。

var a = ["a": 100]
var b = ["b": 200]
a.merge(b) { (current, _) in current }
print(a) // ["a": 100, "b": 200]

同じKeyがあった場合にどちらを採用するかは、クロージャーの返り値で指定するることができます。第1引数は自身の値で、第2引数は結合対象(ここではb)の値です。この例では第1引数をそのまま返しているので、a の値が採用されます。

ちなみに、mergeのクロージャーは本来引数を2つ指定する必要があるのですが、クロージャー内では第2引数を全く使っていないので、こういう場合Swiftでは変数名の代わりに_(アンダーバー)を使用します。

おさらい

辞書型のプロパティやメソッドは配列の時にご紹介したものとほぼ同じなので、すんなり理解できたのではないでしょうか。

ループ処理を行う時は並び順が保証されていないことを念頭においておきましょう。(実は Swift 5 から「KeyValuePairs」という、順番が保証された辞書型のようなものが登場したのですが、それはまたいつかの機会にご紹介できればと思います)

次は分岐処理についてご紹介します。

この記事が気に入ったらサポートをしてみませんか?