lisp - Clojure: iterate over map of sets -
this pretty follow-up last question (clojure idiomatic way update multiple values of map), not quite same. (keep in mind i'm new clojure , functional languages alike)
suppose have following data structure, defined map of sets:
(def m1 {:1 #{2} :2 #{1 3} :3 #{1}})
and map of maps such:
(def m2 {:1 {:1 0 :2 12 :3 23} :2 {:1 23 :2 0 :3 4} :3 {:1 2 :2 4 :3 0}})
what want update registries of m2
have correspondence in m1 value. let's value want x
. resulting m2
this:
{:1 {:1 0 :2 x :3 23} :2 {:1 x :2 0 :3 x} :3 {:1 x :2 4 :3 0}}
assuming v
contains every possible key map, y first attempt, (that failed miserably) this: (assume x=1
(for [i v] reduce (fn [m j] (assoc-in m [i j] 1)) d (i m1)))
needless failure. so, how idiomatic way this?
as understand requirements want to
- produce number of key-sequences
m1
. - in
m2
associate each of key-sequences particular constant value.
the first step simple transformation of m1
. want produce 0 or more key-seqs each entry (depending on how many in set), natural go-to me mapcat
. stands map
-then-concat
, great such case each element of seq produce 0 or more of elements want.
(defn key-seqs [coll] (mapcat (fn [[k v]] (map (partial vector k) v)) coll)) (key-seqs m1) ;;=> ([:1 2] [:2 1] [:2 3] [:3 1])
note function taken mapcat
map
, produces sequence (possibly empty) mapcat
unroll. returning longs stored in sets themselves. if want turn them keywords match m2
need little more processing:
(defn key-seqs [coll] (mapcat (fn [[k v]] (map (comp (partial vector k) keyword str) v)) coll)) (key-seqs m1) ;;=> ([:1 :2] [:2 :1] [:2 :3] [:3 :1])
(we need use str
because keyword
doesn't know longs. keywords not numbers, names symbolic meaning)
then can adapt update-m
previous question little bit can take constant value argument , handle key-sequences don't have same value twice:
(defn update-m [m x v] (reduce (fn [m' key-seq] (assoc-in m' key-seq x)) ;; accumulate changes m ;; initial-value v)) ;; collection loop on
and seem in business:
(update-m m2 1 (key-seqs m1)) ;;=> {:1 {:1 0, :2 1, :3 23}, :2 {:1 1, :2 0, :3 1}, :3 {:1 1, :2 4, :3 0}}
Comments
Post a Comment