online - clojure web framework
Iterato sobre todas las claves del mapa anidado (2)
Dado:
{:o {:i1 1
:i2 {:ii1 4}}}
Me gustaría iterar sobre las teclas del mapa en forma "absoluta" desde la raíz como un vector. Entonces me gustaría:
{
[:o :i1] 1
[:o :i2 :ii1] 4
}
Como el resultado. Básicamente solo obtener los nodos de hoja.
Parece que esto es básicamente un aplanar de las claves anidadas. Esto también parece ser un problema de 4clojure .
Una búsqueda de mapa plano en github produce muchos resultados.
Un ejemplo de implementación:
(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)))))))
Ejemplo
(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}
Una versión aún más general de 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)))
Ejemplo:
(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])
Una versión que creo que es bastante más agradable, utilizando for
lugar de mapcat
:
(defn flatten-keys [m]
(if (not (map? m))
{[] m}
(into {}
(for [[k v] m
[ks v''] (flatten-keys v)]
[(cons k ks) v'']))))
La función es naturalmente recursiva, y el caso base más conveniente para un no mapa es "este valor único, sin keyseq que conduce a él". Para un mapa, puede simplemente llamar flatten-keys
en cada valor en el mapa y anteponer su clave a cada segmento de clave del mapa resultante.