The jist
This example:
- Takes a collection (in this case, a string)
- Gets the groups of repeating letters
- Maps over the groups to get the representative letter
- Maps over the groups to get the count of each group
- Maps over #3 and #4 to get a key-value tuple, the letter and the number of times it repeats (for this instance, not all time).
The jist+
On your four bullets:
- Yup, it's a single-arity function defined with the
defn macro
- Yup, and
identity returns the argument
;; Possible values: 1, :a, #(+ 1 2), {:a [1 2]}
(identity 1) ;;=> 1
(identity :a) ;;=> :a
(identity #(+ 1 2)) ;;=> #function[boop.core/eval7764/fn--7765]
(identity {:a [1 2]}) ;;=> {:a [1 2]}
(partition-by identity "aaaabbbcca") ;;=> (\a \a \a \a) (\b \b \b) (\c \c) (\a))
Just in case you don't understand partition-by, it creates a new group each time the value of the function changes. #(< 3 %) will be false for 1, 2. Because the results are identical, they're grouped together. 3 4 5 will have the same result, so they'll be grouped together.
;; f
;; =
;; number?
;; coll
;; [1 2 3 4 5]
;; [:a :b '(:Yo) 3]
;; f1 coll1
(partition-by #(= 3 %) [1 2 3 4 5]) ;;=> ((1 2) (3) (4 5))
;; f1 coll2
(partition-by #(= 3 %) [:a :b '(:Yo) 3]) ;;=> ((:a :b (:Yo)) (3))
;; f2 coll1
(partition-by number? [1 2 3 4 5]) ;;=> ((1 2 3 4 5))
;; f2 coll2
(partition-by number? [:a :b '(:Yo) 3]) ;;=> ((:a :b (:Yo)) (3))
- Yes, you bind the previous operation to
x. This example maps two maps, so it would've been clearer if they bound the two maps to variables:
(defn chop-chop [coll]
(let [x (partition-by identity coll)
;; Could bind the two maps here
first-letter-map (map (comp str first) x)
repeating-letter-count (map count x)]
;; a map of maps
(map list first-letter-map repeating-letter-count)))
(chop-chop "aaaabbbcca") ;;=> (("a" 4) ("b" 3) ("c" 2) ("a" 1))
- On the last bit of code:
Maps can map over one or more collections.
Here's one collection per map:
;; maps
;; (map (comp str first) x)
;; (map count x)
;; coll
;; [["woo" "yes"] ["hello" "world"]]
;; ((\a \a \a \a) (\b \b \b) (\c \c) (\a)), the result of (partition-by identity "aaaabbbcca")
;; m1 c1
(map (comp str first) [["woo" "yes"] ["hello" "world"]]) ;;=> ("woo" "hello")
;; m1 c2
(map (comp str first) '((\a \a \a \a) (\b \b \b) (\c \c) (\a))) ;;=> ("a" "b" "c" "a")
;; m2 c1
(map count [["woo" "yes"] ["hello" "world"]]) ;;=> (2 2)
;; m2 c2
(map count '((\a \a \a \a) (\b \b \b) (\c \c) (\a))) ;;=> (4 3 2 1)
Here's two collections per map:
;; function
;; #(str (first %1) (first %2))
;; #(list (count %1) (count %2))
;; same colls, but passed in at the same time
;; [["woo" "yes"] ["hello" "world"]]
;; ((\a \a \a \a) (\b \b \b) (\c \c) (\a))
(def c1 [["woo" "yes"] ["hello" "world"]])
(def c2 '((\a \a \a \a) (\b \b \b) (\c \c) (\a)))
(map #(str (first %1) (first %2)) c1 c2) ;;=> ("wooa" "hellob")
(map #(list (count %1) (count %2)) c2 c1) ;;=> ((4 2) (3 2))
You should also understand comp:
;; comp vs. personall const
;; (comp str first)
;; #(str (first %))
;; seq
;; [\a "Wow"]
;; [132 :a]
;; c1 s1
((comp str first) [\a "Wow"]) ;;=> "a"
;; c2 s1
(#(str (first %)) [\a "Wow"]) ;;=> "a"
;; c1 s2
((comp str first) [132 :a]) ;;=> "132"
;; c2 s2
(#(str (first %)) [132 :a]) ;;=> "132"
Welcome to the Clojure community!
(for [x (partition-by identity "aaaabbbcca")] [(first x) (count x)])(map (juxt first count) (partition-by identity "aaaabbbcca"))