clojureでmapを扱う基本的な関数
clojureを何も知らないままとりあえず1つプログラム書いてみて、色々知らないまま書いていたのでとても苦労しました
便利な関数がいっぱいあったのでメモ。
ネストしたmapの操作
jsonを扱っていると時にネストの深いhash-mapをいじらないといけない時がありますね
get-in
こんなxがあったとき、おどろくべきことに一々(:key1 (:key2 ...と書いていました。恐ろしい
user=> (def x {:foo {:bar {:baz 1} :hoge 2}})
#'user/x
user=> (:baz (:bar (:foo x)))
1
get-inという関数がちゃんと用意されていました。
user=> (get-in x [:foo :bar :baz]) 1
assoc-in
key valueを追加したい、もしくは単に値を変えたい場合はassoc-in
assoc-inを知るまではこんなふうに書いていましたが、
user=> (assoc x :foo (assoc (:foo x) :hoge 10))
{:foo {:hoge 10, :bar {:baz 1}}}
これで十分です。
user=> (assoc-in x [:foo :bar :piyo] 10)
{:foo {:hoge 2, :bar {:piyo 10, :baz 1}}}
update-in
関数を適用して更新したいときはupdate-in
user=> (defn f [x] (+ x 10))
#'user/f
user=> (update-in x [:foo :hoge] f)
{:foo {:hoge 12, :bar {:baz 1}}}
ちょっと違うかもだけどけど->
第1引数(?)にその後に続く関数(?)を適用していける感じのマクロ。 これを使えばこんな風になります
user=> (-> x :foo :bar :baz) 1
jsonを使うときのメモ
clojureでjsonといえば、https://github.com/clojure/data.jsonを使いますよね(多分)
これ、普通に使うと文字列からjsonにデコードする時にキーがstringになってしまうんですね。
これは不便。
(get (get (get x "foo") "bar") "baz")
みたいになってしまう。(はず)
しかし、githubのREADMEの例にも書いてあるように、
(json/read-str "{\"a\":1,\"b\":2}"
:key-fn keyword)
このように:key-fn keywordを指定すればキーがKeywordになってくれます!
便利