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

  1. produce number of key-sequences m1.
  2. 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

Popular posts from this blog

java - Date formats difference between yyyy-MM-dd'T'HH:mm:ss and yyyy-MM-dd'T'HH:mm:ssXXX -

c# - Get rid of xmlns attribute when adding node to existing xml -