環境
- Elixir 1.x
やりたいこと
例えば、以下のようなMapがあったとする。
user = %{name: "Taro", gender: "man", city: "Tokyo"}
ここのcityのTokyoの値を変更したり、あたらしくidのキーを追加したい。
存在するキーを更新する場合
パイプ文字を使った new_map = %{ old_map | key => value, ...}
を使う。
new_user = %{user| city: "sendai"} # => %{city: "sendai", gender: "man", name: "Taro"}
引数に続けば複数一括更新できる。
new_user = %{user | city: "sendai", name: "Ziro"}
キーが存在しなかった場合エラーになる。
iex(10)> new_user = %{user| id: 123} ** (KeyError) key :id not found in: %{city: "Tokyo", gender: "man", name: "Taro"} (stdlib) :maps.update(:id, 123, %{city: "Tokyo", gender: "man", name: "Taro"}) (stdlib) erl_eval.erl:255: anonymous fn/2 in :erl_eval.expr/5 (stdlib) lists.erl:1263: :lists.foldl/3
キーが存在しない場合
Map.put_new/3
を使う必要がある。
new_user = Map.put user, :id, 123 # => %{city: "Tokyo", gender: "man", id: 123, name: "Taro"}
こっちはキーが存在していても更新される。
new_user = Map.put user, :city, "sendai" # => %{city: "sendai", gender: "man", name: "Taro"}
このように書くこともできる。
user |> Map.put(:city, "sendai")
Map.merge/2
も利用可能
Map.merge(user, %{city: "sendai"} )
じゃあキーの有無考えなくていい Map.put
全部使えばいいじゃんって話だが、本来存在しなきゃいけないときに気づけない場合もある。
ちゃんと使いどきを考えよう