In addition to commonly known `reduce` function Clojure has its specialized version called `reduce-kv`. This function is designed to work with associative collections (like map or vector). Here is its signature:

``(reduce-kv f init coll)``

where:

• `f` is a 3 arguments function that takes init (or previous) value as a first argument, key as second and the key value as the last
• `init` is a base value for a reduce operation
• `coll` is an associative collection on which reduce operation will work

The final result is computed in such way that first function `f` is applied to the `init` value and the first key and the first value in the collection. Next `f` is applied the the previous result and the second key and value. This algorithm is repeated till all keys and values are processed. If supplied collection has no key value pairs (is empty) then `init` value is returned.

Because in Clojure vector is an associative collection (where every value in a vector has corresponding integer value starting from `0`) `recuce-kv` function can be used for it.

Let’s look at the few examples:

• Let’s say that for such map: `{:a [1 2 3] :b [5 4 6] :c [20 21 100]}` we want to shuffle vectors corresponding to keys. To do that we can write this code:
``````(reduce-kv (fn [m k v]
(assoc m k (shuffle v)))
{}
{:a [1 2 3], :b [5 4 6], :c [20 21 100]})

=> {:a [3 1 2], :b [4 6 5], :c [21 100 20]}``````
• In different scenario let’s say we have a map with product names and their price:
``(def products {:phone 200 :tv 300 :pc 100 :xbox 150})``

and we want to sum the prices only for `:phone`, `:tv` and `:xbox`. To do that we can write something like this:

``````(reduce-kv (fn [s k v]
(if (#{:phone :tv :xbox} k)
(+ s v) s))
0 products)

=> 650``````
• In the last example let’s look how we could sum numbers in the vector that are only at the even positions:
``````(def numbers (vec (range 10)))
=> [0 1 2 3 4 5 6 7 8 9]

(reduce-kv (fn [s k v]
(if (even? k) (+ s v) s))
0 numbers)
=> 20``````

In this case please remember that `reduce-kv` works, because it operates on a vector - which is associative collection (in essence, it implements `IKVReduce` protocol). If the same code would be invoked for a `list` we would get such error:

``````IllegalArgumentException No implementation of method: :kv-reduce of protocol:
#'clojure.core.protocols/IKVReduce found for class: clojure.lang.PersistentList``````