Iterate over all keys of nested map

匿名 (未验证) 提交于 2019-12-03 02:33:02

问题:

Given:

{:o {:i1 1      :i2 {:ii1 4}}} 

I'd like to iterate over the keys of the map in "absolute" form from the root as a vector. So I'd like:

{  [:o :i1] 1  [:o :i2 :ii1] 4 } 

As the result. Basically only get the leaf nodes.

回答1:

A version that I think is rather nicer, using for instead of mapcat:

(defn flatten-keys [m]   (if (not (map? m))     {[] m}     (into {}           (for [[k v] m                 [ks v'] (flatten-keys v)]             [(cons k ks) v'])))) 

The function is naturally recursive, and the most convenient base case for a non-map is "this one value, with no keyseq leading to it". For a map, you can just call flatten-keys on each value in the map, and prepend its key to each keyseq of the resulting map.



回答2:

Looks like this is basically a flatten of the nested keys. This also seems to be a 4clojure problem.

A flatten-map search on github yield many results.

One example implementation:

(defn flatten-map    "Flattens the keys of a nested into a map of depth one but     with the keys turned into vectors (the paths into the original     nested map)."   [s]   (let [combine-map (fn [k s] (for [[x y] s] {[k x] y}))]     (loop [result {}, coll s]       (if (empty? coll)         result         (let [[i j] (first coll)]           (recur (into result (combine-map i j)) (rest coll))))))) 

Example

(flatten-map {:OUT               {:x 5                :x/A 21                :x/B 33                :y/A 24}}) => {[:OUT :x] 5, [:OUT :x/A] 21, [:OUT :x/B] 33, [:OUT :y/A] 24} 

An even more general version from Christoph Grand:

(defn flatten-map   "Take a nested map (or a nested collection of key-value pairs) and returns a    sequence of key-value pairs where keys are replaced by the result of calling    (reduce f pk path) where path is the path to this key through the nested    maps."   ([f kvs] (flatten-map f nil kvs))   ([f pk kvs]    (mapcat (fn [[k v]]              (if (map? v)                (flatten-map f (f pk k) v)                [[(f pk k) v]])) kvs))) 

Example:

(flatten-map conj [] {:OUT               {:x 5                :x/A 21                :x/B 33                :y/A 24}}) => ([[:OUT :x] 5] [[:OUT :x/A] 21] [[:OUT :x/B] 33] [[:OUT :y/A] 24]) 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!