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)