Iterate over all keys of nested map

送分小仙女□ 提交于 2019-12-31 01:41:48

问题


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])


来源:https://stackoverflow.com/questions/32853004/iterate-over-all-keys-of-nested-map

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