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 :when
modifier. 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)