kitoko552.memo

kitoko552のメモ

Dictionaryの配列をひとつのDictionaryにする

要点

  • Dictionaryの配列をひとつのDictionaryにするにはreduceを使う。
let array = [["one" : 1], ["two" : 2], ["three" : 3]]
let dictionary = array.flatMap { $0 }.reduce([String : Int]()) { (var dict, tuple) in
    dict[tuple.0] = tuple.1
    return dict
}

print(dictionary) // ["one" : 1, "two" : 2, "three" : 3]

Dictionaryの配列をflatMapすると

最近Dictionaryの配列を扱いました。
コードで書くと以下のようなものです。

let array = [["one" : 1], ["two" : 2], ["three" : 3]]

私はDictionaryの配列をひとつのDictionaryにする必要がありました。
以下のようにしたかったのです。

let dictionary = ["one" : 1, "two" : 2, "three" : 3]

これを実現するため、なんとなくイメージでflatMapすればいけるのではと思いやってみると、

let dictionary = array.flatMap { $0 }
//  [("one" : 1), ("two" : 2), ("three" : 3)]

!!
なんとDictionaryの配列がタプルの配列になっただけでした。

Dictionaryの配列のflatMapは、タプルの配列になるのです。

reduceを使う

じゃあどうしたかというと、reduceを使って割と強引にDictionaryを生成しました。

let array = [["one" : 1], ["two" : 2], ["three" : 3]]
let dictionary = array.flatMap { $0 }.reduce([String : Int]()) { (var dict, tuple) in
    dict[tuple.0] = tuple.1
    return dict
}

print(dictionary) // ["one" : 1, "two" : 2, "three" : 3]

↓のStackOverflowを参考にしました。

stackoverflow.com

もうちょっとかっこよく書ければいいのですが、思いつくのはこれしかありませんでした。
もっとスマートに書く方法を知っていたら是非教えてください。

reduceについて

reduceがよくわからい方向けに補足します。
reduceは要素をまとめてひとつのものにしたいときに使います。

例えば、配列の中の値を全て足しあわせたいとき。

let array = [1, 2, 3, 4, 5]
let all = array.reduce(0) {
    $0 + $1
}

print(all) // 15

reduceの第一引数は初期値です。
上の例だと0が初期値で、0+1, 1+2, 3+3, 6+4, 10+5の順番で計算されます。

今回の、Dictionaryの配列をひとつのDictionaryにするために使ったreduceは少しだけ応用的ですが、基本は上の足しあわせと同じです。
初期値は[String : Int]型の空のDictionaryで、そこからタプルの値をkeyとvalueに分けて追加していきます。
処理を順番に書くと、[:], ["one" : 1], ["one" : 1, "two" : 2], ["one" : 1, "two" : 2, "three" : 3]となります。

これでもわからない人はググりましょう!