2013年1月22日火曜日

[Clojure]mapの操作

Clojureでmapを作成・操作する関数のメモ。多くの関数は他のシーケンス・コレクションにも適用可能。

(def a-map {:k1 :v1 :k2 :v2})

;;; get関数でアクセスできる
(get a-map :k1)
;; => :v1
(get a-map :not-found)
;; => nil
(get a-map :not-found :default)
;; => :default

;;; キーワードはマップへのアクセサとして扱える
(:k1 a-map)
;; => :v1
(:not-found a-map)
;; => nil
(:not-found a-map :default)
;; => :default

;;; マップ自体をキーを引数に取る関数として扱える
(a-map :k2)
;; => :v2
(a-map :not-found)
;; => nil
(a-map :not-found :default)
;; => :default

;;; find関数でアクセスするとキーと値のペア(map entry)が取得できる
(find a-map :k2)
;; => [:k2 :v2]
(find a-map :not-found)
;; => nil

;;; すべてのキーを取得する
(map key {:k1 :v1 :k2 :v2})
;; => (:k1 :k2)
(keys {:k1 :v1 :k2 :v2})
;; => (:k1 :k2)

;;; すべての値を取得する
(map val {:k1 :v1 :k2 :v2})
;; => (:v1 :v2)
(vals {:k1 :v1 :k2 :v2})
;; => (:v1 :v2)

;;; 複数のキーに対応する値を取得する
(select-keys {:k1 :v1 :k2 :v2 :k3 :v3} [:k1 :k3])
;; => {:k3 :v3, :k1 :v1}
((juxt :k1 :k3) {:k1 :v1 :k2 :v2 :k3 :v3})
;; => [:v1 :v3]

;;; 一部を抜き出す (sorted-map)
(subseq (sorted-map 1 2 3 4 5 6) <= 3)
;; => ([1 2] [3 4])

;;; 要素を追加する
(assoc a-map :k3 :v3)
;; => {:k3 :v3, :k1 :v1, :k2 :v2}
(assoc a-map :k3 :v3 :k4 :v4)
;; => {:k4 :v4, :k3 :v3, :k1 :v1, :k2 :v2}
(conj a-map [:k3 :v3])
;; => {:k3 :v3, :k1 :v1, :k2 :v2}
(conj a-map [:k3 :v3] [:k4 :v4])
;; => {:k4 :v4, :k3 :v3, :k1 :v1, :k2 :v2}
(merge {:k1 :v1} {:k2 :v2})
;; => {:k2 :v2, :k1 :v1}
(merge {:k1 :v1} [:k2 :v2])
;; => {:k2 :v2, :k1 :v1}
(merge-with concat {:k1 [1 2]} {:k1 [3 4]})
;; => {:k1 (1 2 3 4)}
(into {:k1 :v1} {:k2 :v2})
;; => {:k1 :v1, :k2 :v2}
(into {:k1 :v1} [[:k2 :v2]])
;; => {:k1 :v1, :k2 :v2}

;;; 指定したキーを削除
(dissoc {:k1 :v1 :k2 :v2} :k1)
;; => {:k2 :v2}
(dissoc {:k1 :v1 :k2 :v2} :k1 :k2)
;; => {}

;;; 空かどうかチェックする
(if (empty? {}) :a :b)
;; => :a
(if (empty? {:key :val}) :a :b)
;; => :b
(if (not-empty {}) :a :b)
;; => :b
(if (not-empty {:key :val}) :a :b)
;; => :a
(if (seq {}) :a :b)
;; => :b
(if (seq {:key :val}) :a :b)
;; => :a

;;; 指定したキーが存在するかチェックする
(contains? {} :key)
;; => false
(contains? {:key :val} :key)
;; => true


;;; alist風のベクタからマップを作成する
(def alist [[1 2] [3 4]])

(into {} alist)
;; => {1 2, 3 4}

(apply merge {} alist)
;; => {3 4, 1 2}

(apply conj {} alist)
;; => {3 4, 1 2}

;;; plist風のベクタからマップを作成する
(def plist [1 2 3 4])

(apply assoc {} plist)
;; => {3 4, 1 2}

(apply sorted-map plist)
;; => {1 2, 3 4}

;;; keyのベクタとvalsのベクタからマップを作成する
(def ks [1 3])
(def vs [2 4])

(zipmap ks vs)
;; => {3 4, 1 2}

(apply assoc {} (interleave ks vs))
;; => {3 4, 1 2}

;;; ネストしたマップへアクセスする
(get-in {:a {:b 2}} [:a :b])
;; => 2

(get-in {} [:a :b] :default)
;; => :default

(assoc-in {} [:a :b] 2)
;; => {:a {:b 2}}

(update-in {:a {:b 2}} [:a :b] inc)
;; => {:a {:b 3}}


;;; その他
(frequencies [:a :b :a :a :c]) ; 出現回数
;; => {:a 3, :b 1, :c 1}

(group-by even? [1 2 3 4]) ; 関数の適用結果によるグループ分け
;; => {false [1 3], true [2 4]}

0 件のコメント:

コメントを投稿