3

让我们制作频率图:

(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"])

看起来非常相似,有什么优点/缺点?表现?

4

3 回答 3

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)代码,该代码在具有高度性能意识的同时非常惯用。

于 2013-09-08T18:53:33.650 回答
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

于 2013-09-08T18:47:25.287 回答
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}

于 2019-12-19T14:12:03.400 回答