Clojure - 计算嵌套映射中嵌套键的出现次数?

时间:2018-01-22 12:13:42

标签: clojure edn

我有一个像这样的嵌套地图:

{:A {:B {:A {:B {:A {:B 0}}}}}}

我想计算一对[:A:B]的出现次数,以便在上面的情况下,结果为3.

我最初的想法是使用clojure.walk/postwalk来遍历地图并增加一个计数器。

是否有更优化的方法来实现这一目标?

3 个答案:

答案 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)