Kiran Gangadharan

Different applications of reduce in Clojure

I’ve just started learning Clojure using Clojure for the Brave and True and solving problems on 4Clojure. While doing so, I’ve noticed that a lot of problems that seem tricky can be quickly solved using clojure.core/reduce.

This post is an effort to document some snippets to demonstrate how useful reduce can be.

Reverse a collection

1
2
3
4
5
6
(defn myreverse [coll]
  (reduce conj '() coll))

(myreverse '(1 2 3 4))

;; (4 3 2 1)

Find frequency of words in a string

1
2
3
4
5
6
7
8
9
(defn freq [str]
  (reduce #(assoc %1 %2 (inc (%1 %2 0)))
          {}
          (clojure.string/split str #"\s")))

(freq "Hey there! I am the hey man! I like to hey the people")

;; {"like" 1, "people" 1, "man!" 1, "am" 1, "Hey" 1,
;;  "hey" 2, "there!" 1, "I" 2, "to" 1, "the" 2}

Transform all values in a map

1
2
3
4
5
6
(reduce (fn [new-map [key val]]
          (assoc new-map key (inc val)))
        {}
        {:lat 50.23 :lng 24.21})

;; {:lat 51.23, :lng 25.21}

Using reduce to filter out values in map

1
2
3
4
5
6
7
8
(reduce (fn [new-map [key val]]
          (if (> val 3)
            (assoc new-map key val)
            new-map))
        {}
        {:a 2 :b 4 :c 3 :d -1 :e 9 :f 23})

;; {:b 4, :e 9, :f 23}

Implementing a mapping function

1
2
3
4
5
6
7
8
(defn mapr [f coll]
  (reverse (reduce (fn [new-seq elem]
            (conj new-seq (f elem)))
          (list) coll)))

(mapr (fn [x] (* x 2)) [1 2 3 4])

;; (2 4 6 8)

Sort list of list based on sum of elements

1
2
3
(sort-by #(reduce + %) ['(8 8 7) '(1 2 3) '(6 5 7)])

;; ((1 2 3) (6 5 7) (8 8 7))

Generate Fibonacci series

 1
 2
 3
 4
 5
 6
 7
 8
 9
10

;; Generate first 10 fibonacci numbers

(reduce
  (fn [a b]
    (conj a (+ (last a) (last (butlast a)))))
  [0 1]
  (range 8))

;; [0 1 1 2 3 5 8 13 21]

Finding factorial

1
2
(defn factorial [n]
  (reduce * (range 1 (inc n))))

Implementing comp

1
2
3
(fn [& fs]
  (fn [& xs]
    (first (reduce #(vector (apply %2 %1)) xs (reverse fs)))))