Reduce
(reduce f coll) (reduce f val coll)
f
should be a function of 2 arguments. If val is not supplied, returns the result of applying f
to the first 2 items in coll
, then applying f
to that result and the 3rd item, etc. If coll
contains no items, f
must accept no arguments as well, and reduce returns the result of calling f
with no arguments. If coll
has only 1 item, it is returned and f
is not called. If val
is supplied, returns the result of applying f
to val
and the first item in coll
, then applying f
to that result and the 2nd item, etc. If coll contains no items, returns val
and f
is not called.
(reduce + [1 2 3 4 5]) (reduce + []) (reduce + [1]) (reduce + [1 2]) (reduce + 1 []) (reduce + 1 [2 3])
Converting a vector to a set:
(reduce conj {} [:a :b :c])
Calculate primes until 1000
(reduce (fn [primes number] (if (some zero? (map (partial mod number) primes)) primes (conj primes number))) [2] (take 1000 (iterate inc 3)))
Add one collection to another (combining sequences is done with cons):
(reduce conj [1 2 3] [4 5 6])
(reduce (cons %2 %1) [1 2 3] [4 5 6])
Combine a vector of collections into a single collection of the type of the first collection in the vector.
(reduce into [[1 2 3] [:a :b :c] ([4 5] 6)])
The flatten function can be used to completely fuse all of the items of a nested tree into a single sequence. Sometimes all that is needed is to fuse the first level of a tree. This can be done with reduce
and into
.
(reduce into [] ([] [[10 18]] [[8 18]] [[10 12]] [[0 -6]] [[2 6]]))
Some functions update a collection with a single item. A number of functions have a 'more' argument which lets them work over collections. These functions can benefit 'reduce' which lets them work a collection of items...
(into {} {:dog :food})
(reduce into {} [{:dog :food} {:cat :chow}])
The reduction will terminate early if an intermediate result uses the reduced
function.
(defn limit [x y] (let [sum (+ x y)] (if (> sum 10) (reduced sum) sum))) (reduce + 0 (range 10)) (reduce limit 0 (range 10))
This will generate the first 100 Fibonacci numbers:
(reduce (fn [a b] (conj a (+' (last a) (last (butlast a))))) [0 1] (range 98))
Reduce can be used to reimplement a map function:
(defn map* [f & c] (let [c* (partition (count c) (apply interleave c))] (reduce (fn [s k] (conj s (apply f k))) [] c*))) (map* * [0.5 0.5 0.5] (range)) (map* str "clojure" (range))
Update map entries:
(defn update-map-entries [m e] (reduce (update-in %1 [(first %2)] (fn [_] (last %2))) m e)) (update-map-entries {:a 1 :b 2 :c 3} {:a 5 :b 9}) (update-map-entries {:a 1 :b 2 :c 3} {:a 5 :b 9 :d 8})
Flatten values in a map.
(require [clojure.set :as set]) (reduce (fn [flattened [k v]] (set/union flattened v)) {} {:e {:m :f}, :c {:f}, :b {:c :f}, :d {:m :f}, :a {:c :f}})
A simple factorial function using reduce:
(defn fact [x] (reduce * (range 1 (inc x))))
Reduce over maps by destructuring keys:
(def x {:a 1 :b 2}) (reduce (fn [p [k v]] (into p {k (+ 1 v)})) {} ; First value for p x)
A practical example of mapping over values in a hash-map with the upper-case
function:
(reduce (fn [acc [k v]] (assoc acc k (clojure.string/upper-case v))) {} {:a "aaaaaaa" :b "bbbbbbb"})