的所有的鍵:遍歷鑑於嵌套地圖
{:o {:i1 1
:i2 {:ii1 4}}}
我想迭代中從根作爲載體「絕對」形式的地圖的鍵。所以我想:
{
[:o :i1] 1
[:o :i2 :ii1] 4
}
因此。基本上只獲得葉節點。
的所有的鍵:遍歷鑑於嵌套地圖
{:o {:i1 1
:i2 {:ii1 4}}}
我想迭代中從根作爲載體「絕對」形式的地圖的鍵。所以我想:
{
[:o :i1] 1
[:o :i2 :ii1] 4
}
因此。基本上只獲得葉節點。
,我認爲一個版本是相當漂亮,使用for
代替mapcat
:
(defn flatten-keys [m]
(if (not (map? m))
{[] m}
(into {}
(for [[k v] m
[ks v'] (flatten-keys v)]
[(cons k ks) v']))))
功能自然是遞歸的,而對於非地圖最方便的基本情況是「這一個值,沒有keyseq導致它「。對於地圖,您可以在地圖上的每個值上調用flatten-keys
,並將其密鑰添加到結果地圖的每個keyseq中。
值得注意的是,因爲它只是咬我一口:如果你在地圖中保存記錄,這將會遍歷這些記錄(並且把所有的東西搞亂),因爲'(map?m)'對於記錄是真的。我改變了我的實現,以保持記錄。 – ClojureMostly
看起來這基本上是嵌套鍵的扁平化。這也似乎是a 4clojure problem。
A flatten-map search on github產生許多結果。
一個示例實現:
(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)))))))
例
(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}
一個甚至從克里斯托弗大更一般的版本:
(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)))
實施例:
(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])
原來,它基本上是一個平坦的鍵:http://stackoverflow.com/questions/17901933/flattening-a-map-by-join-the-keys – ClojureMostly
重複?還是應該回答? – ClojureMostly