让我们制作频率图:
(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"])
似乎非常相似,有什么利弊?性能
答案 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}