Let's make frequency map:
(reduce #(update-in %1 [%2] (fnil inc 0)) {} ["a" "b" "a" "c" "c" "a"])
My concern is expression inside lambda #(...) - is it the canonical way to do it? Can I do it better/shorter?
EDIT: Another way I found:
(reduce #(assoc %1 %2 (inc %1 %2 0)) {} ["a" "b" "a" "c" "c" "a"])
Seems like very similar, what are pros/cons? Performance?
Since Clojure 1.2, there is a frequencies function in clojure.core:
user=> (doc frequencies)
-------------------------
clojure.core/frequencies
([coll])
Returns a map from distinct items in coll to the number of times
they appear.
Example:
user=> (frequencies ["a" "b" "a" "c" "c" "a"])
{"a" 3, "b" 1, "c" 2}
It happens to use transients and ternary get; see (source frequencies) for the code, which is as idiomatic as it gets while being highly performance-aware.
There is no need to use update-in. My way would be:
(defn frequencies [coll]
(reduce (fn [m e]
(assoc m e (inc (m e 0))))
{} coll))
Update: I assumed you knew frequencies was in core also and this was just an exercise.
I did a guest lecture a while ago in which I explained how you can get to this solution step by step. Won't be much new for you, since you were already close to the core solution, but maybe it is of value to someone else reading this question. The slides are in Dutch. If you change .html to .org it's easier to get the source code:
http://michielborkent.nl/gastcollege-han-20-06-2013/gastcollege.html http://michielborkent.nl/gastcollege-han-20-06-2013/gastcollege.org
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With