Clojure:频率图的惯用代码

时间:2013-09-08 18:42:34

标签: clojure

让我们制作频率图:

(reduce #(update-in %1 [%2] (fnil inc 0)) {} ["a" "b" "a" "c" "c" "a"])

我担心的是lambda #(...)里面的表达 - 这是规范的方式吗?我可以做得更好/更短吗?

编辑:我找到的另一种方式:

(reduce #(assoc %1 %2 (inc %1 %2 0)) {} ["a" "b" "a" "c" "c" "a"])

似乎非常相似,有什么利弊?性能

3 个答案:

答案 0 :(得分:9)

自Clojure 1.2以来,frequencies中有一个clojure.core函数:

user=> (doc frequencies)
-------------------------
clojure.core/frequencies
([coll])
  Returns a map from distinct items in coll to the number of times
  they appear.

示例:

user=> (frequencies ["a" "b" "a" "c" "c" "a"])
{"a" 3, "b" 1, "c" 2}

碰巧使用瞬态和三元get;请参阅(source frequencies)以获取代码,该代码在高度提升性能的同时具有惯用效果。

答案 1 :(得分:1)

无需使用update-in。我的方式是:

(defn frequencies [coll]
  (reduce (fn [m e]
              (assoc m e (inc (m e 0))))
          {} coll))

更新:我认为你知道frequencies也是核心,这只是一个练习。

前段时间我做了一次客座讲座,其中我解释了如何逐步解决这个问题。对你来说不是什么新鲜事,因为你已经接近core解决方案,但也许对于阅读这个问题的其他人来说它是有价值的。幻灯片是荷兰语。如果您将.html更改为.org,则更容易获得源代码:

http://michielborkent.nl/gastcollege-han-20-06-2013/gastcollege.html http://michielborkent.nl/gastcollege-han-20-06-2013/gastcollege.org

答案 2 :(得分:0)

仅使用“关联”和递归的另一种方法:

(defn my-frequencies-helper [freqs a-seq]
  (if (empty? a-seq)
    freqs
    (let [fst (first a-seq)
          new_set (if (contains? freqs fst)
                    (assoc freqs fst (inc (get freqs fst)))
                    (assoc freqs fst 1))]
      (my-frequencies-helper new_set (rest a-seq)))))

(defn my-frequencies [a-seq]
  (my-frequencies-helper {} a-seq))
  

(我的频率[1 1 2 2:D:D:D])

     

=> {1 2,2 2,:D 3}

     

(我的频率[:a“ moi”:a“ moi”“ moi”:a 1])

     

=> {:a 3,“ moi” 3,1 1}