Loop Through Map in Clojure


In Clojure, basic maps are unordered. But we can loop through them. Let's get goin' round the track.

(Note: you can order by keys with sorted-map.)

For Loop

Clojure has a for expression. The function signature:

(for seq-exprs body-expr)

The seq-exprs are to be one or more binding-form pairs (think of a (let [bound-name expr]) expression). Whether there's one or more, they need to be surrounded by [] square brackets, just like a let expression. If there are multiple expressions here, they're looped through as in a nested loop, the right-most (ie, inner-most) first.

The body-expr is what's returned from the expression.

Example: Return All Keys/Values

Let's define a map:

(def stuff {:a 1 :b 2 :c 3 :d 4 :e 5})

Let's loop through and get all the keys:

(for [[k v] stuff] k)
; => (:a :b :c :d :e)

The seq-expr binding-form pair of [[k v] stuff] is destructuring inline, exposing the map key as k and the map value as v.

To get the values, what would we change? The body-expr, or return value:

(for [[k v] stuff] v)
; => (1 2 3 4 5)

Conditional :when

While you loop, you can add a conditional with a :whenmodifier. This modifier goes at the end of the binding-form seq-exprs.

From within the conditional expression, you can reference any other bound values in seq-exprs and must return a boolean.

For example, only return those values that are even:

(for [[k v] stuff :when (even? v)] v)
; => (2 4)