我有一个像这样的嵌套地图:
{:A {:B {:A {:B {:A {:B 0}}}}}}
我想计算一对[:A:B]的出现次数,以便在上面的情况下,结果为3.
我最初的想法是使用clojure.walk/postwalk
来遍历地图并增加一个计数器。
是否有更优化的方法来实现这一目标?
答案 0 :(得分:4)
tree-seq
效果很好:
(defn count-ab [data]
(->> data
(tree-seq coll? seq)
(keep #(get-in % [:A :B]))
count))
user> (def data {:A {:B {:A {:B {:A {:B 0}}}}}})
#'user/data
user> (count-ab data)
3
user> (def data-1 {:A {:B {:C {:A {:B {:A {:B 0}}}}}}})
#'user/data-1
user> (count-ab data-1)
3
user> (def data-2 {:A {:X {:A {:B 100}}
:B {:C {:A {:B {:A {:B 0}}}}}}})
#'user/data-2
user> (count-ab data-2)
4
答案 1 :(得分:1)
因为它的嵌套地图,我的实用主意是递归遍历并计算:
(defn do-count [m]
(loop [m m
counter 0]
(if-let [m* (get-in m [:A :B])]
(recur m* (inc counter))
counter)))
(do-count {:A {:B {:A {:B {:A {:B 0}}}}}}) ;==> 3
答案 2 :(得分:0)
我建议编写一个函数来将深层嵌套的地图转换为由路径
键入的平面地图 (defn flatten-map
"unwind deeply nested map into map of paths and vals"
([m] (into {} (flatten-map [] m)))
([path m]
(if (map? m)
(mapcat (fn [[k v]]
(flatten-map (conj path k) v))
m)
[[path m]])))
您可以使用它来计算相邻的[:a:b]键,如此
(->> {:A {:B {:A {:B {:A {:B 0}}}}}}
flatten-map
keys
(mapcat #(partition 2 1 %))
(filter #(= [:A :B] %))
count)