Different applications of reduce in Clojure

November 2015 · 2 minute read

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

(defn myreverse [coll]
  (reduce conj '() coll))

(myreverse '(1 2 3 4))

;; (4 3 2 1)

Find frequency of words in a string

(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

(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

(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

(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

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

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

Generate Fibonacci series

;; 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

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

Implementing comp

(fn [& fs]
  (fn [& xs]
    (first (reduce #(vector (apply %2 %1)) xs (reverse fs)))))
comments powered by Disqus