Funske van Leeuwen
Funske van Leeuwen

Reputation: 5

Incrementing Values in Clojure Map

I've decided to take the plunge into Clojure. So far, I'm really enjoying thinking about things in immutable and functional ways. However, I've stumbled across a problem that I don't know how to solve elegantly.

I want to apply a map to a set of values, but I want the function being applied to increment for each new value in the collection

Eg.

(def data ["a" "b" "c"])
(map (fn [x] (str x " is item number "  )) data)

I'm trying to map a function over my collection such that the result is:

("a is item number 1" "b is item number 2" "c is item number 3")

Any help our guidance would be appreciated.

Upvotes: 0

Views: 390

Answers (1)

leonardoborges
leonardoborges

Reputation: 5619

What you need is a way to carry some state to your mapping function that contains the index of the current item.

One way to do this is to leverage the fact that map, when given more than one collection as input, acts as a zipper and calls your mapping function with one element from every list.

How does this help? If you make the second collection be an infinite sequence starting at zero, your function will be called with arguments "a" and 0, then "b" and 1 and so forth:

(map (fn [x i] (str x " is item number " (inc i))) data (range))

It turns out that this is a common pattern and Clojure provides a core function - map-indexed - for this purpose:

(map-indexed (fn [i x] (str x " is item number " (inc i))) data)

The only two differences in the second example: the order of arguments is reversed and you don't need to provide the second collection.

Upvotes: 5

Related Questions