(ns example
(:use expectations))
(defn flatten-keys* [a ks m]
(if (map? m)
(reduce into (map (fn [[k v]] (flatten-keys* a (conj ks k) v)) (seq m)))
(assoc a ks m)))
(defn flatten-keys [m] (flatten-keys* {} [] m))
(expect
{[:z] 1, [:a] 9, [:b :c] Double/NaN, [:b :d] 1, [:b :e] 2, [:b :f :g] 10, [:b :f :i] 22}
(flatten-keys {:z 1 :a 9 :b {:c Double/NaN :d 1 :e 2 :f {:g 10 :i 22}}}))
As the test shows, the code converts
{:z 1 :a 9 :b {:c Double/NaN :d 1 :e 2 :f {:g 10 :i 22}}}into
{[:z] 1, [:a] 9, [:b :c] Double/NaN, [:b :d] 1, [:b :e] 2, [:b :f :g] 10, [:b :f :i] 22}Improvement suggestions welcome.
I've had to do the same thing in a recent project and came up with basically the same code. The only difference was I made flatten-keys a multiple arity function so you wouldn't have to clutter your namespace with flatten-keys* and flatten-keys.
ReplyDeletethis works really well -- the only adjustment i made was to the if statement to add a check for empty maps
ReplyDeletelike so
(if (and (map? m) (not (empty? m)))
recur
base case
)
this works well, the only adjustment i made was to check for empty maps -- so something like
ReplyDelete(if (and (map? m) (not (empty? m))) ... )