【问题标题】:Collecting data from nested maps in Clojure从 Clojure 中的嵌套地图中收集数据
【发布时间】:2013-10-14 21:15:29
【问题描述】:

在 Clojure 中计算嵌套映射的某些属性的惯用方法是什么?

给定以下数据结构:

(def x {
    :0 {:attrs {:attributes {:dontcare "something"
                             :1 {:attrs {:abc "some value"}}}}}
    :1 {:attrs {:attributes {:dontcare "something"
                             :1 {:attrs {:abc "some value"}}}}}
    :9 {:attrs {:attributes {:dontcare "something"
                             :5 {:attrs {:xyz "some value"}}}}}})

我怎样才能产生所需的输出:

(= (count-attributes x) {:abc 2, :xyz 1})

这是我迄今为止的最大努力:

(defn count-attributes 
 [input]
 (let [result (for [[_ {{attributes :attributes} :attrs}] x
                 :let [v (into {} (remove (comp not :attrs) (vals attributes)))]]
              (:attrs v))]
      (frequencies result)))

这会产生以下内容:

{{:abc "some value"} 2, {:xyz "some value"} 1}

【问题讨论】:

  • 我认为tree-seq的答案要好得多

标签: clojure


【解决方案1】:

我喜欢用线程构建这样的函数,这样步骤更容易阅读

user> (->> x 
           vals                    ; first throw out the keys
           (map #(get-in % [:attrs :attributes]))  ; get the nested maps
           (map vals)              ; again throw out the keys
           (map #(filter map? %))  ; throw out the "something" ones. 
           flatten                 ; we no longer need the sequence sequences
           (map vals)              ; and again we don't care about the keys
           flatten                 ; the map put them back into a list of lists
           frequencies)            ; and then count them.
{{:abc "some value"} 2, {:xyz "some value"} 1} 

(remove (comp not :attrs) 很像select-keys
for [[_ {{attributes :attributes} :attrs}] 让我想起了get-in

【讨论】:

【解决方案2】:

我发现tree-seq 对于这些情况非常有用:

(frequencies (filter #(and (map? %) (not-any? map? (vals %))) (tree-seq map? vals x)))

【讨论】:

    猜你喜欢
    • 2014-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-19
    相关资源
    最近更新 更多