/img/clojure-banner.png

Two functions in one with `group-by`

Getting the result of a function and it's opposite at one time

Written by: Alex Root-Roatch | Tuesday, November 5, 2024

Filter and Remove

Recently in Aesop we've needed to be able to filter stories by whether they are linked to Jira issues or not. My initial instinct for scenarios like this is to reach for filter and remove — the latter of which take the same predicate function as filter and returns the opposite result.

Clojure being full of cool tricks though, there's a way to accomplish this with in one fell swoop instead of iterating through the collection twice: group-by. This function takes a function and returns a map of the elements in a given sequence grouped by common return values. For example, the predicate function that I would normally pass into filter returns a boolean. When putting this same function into group-by, the result is a map with two keys, true and false, the value of each being a sequence of the elements that yielded each result.

(group-by even? [1 2 3 4 5 6 7 8 9])

=> {true  [2 4 6 8]
    false [1 3 5 7 9]}

Not Just Predicates

Pretty much any function can be used with group-by, though, not just predicates. For example, if we wanted to sort a collection of words by their length:

(group-by count ["the" "quick" "brown" "fox" "jumps" "over" "the" "lazy" "dog"])

=> {3 ["the" "fox" "the" "dog"]
    4 ["over" "lazy"]
    5 ["quick" "brown" "jumps"]}

Sets as Functions

And of course, since code is all just data in functional programming, sets can be used as functions as well to test membership:

(group-by set ["meat" "mat" "team" "mate" "eat" "tea"])

=> {#{\a \e \m \t} ["meat" "team" "mate"],
    #{\a \m \t}    ["mat"], 
    #{\a \e \t}    ["eat" "tea"]}

Conclusion

This definitely seems like one of those functions that can be used in a lot of different ways, especially when it comes to using custom functions inside it. This is what I like to call a "Swiss Army knife" function: it's good to have in your pocket because you never know when it might come in handy, and you just might find yourself using it for something you wouldn't have thought of until that moment.

Explore more articles

Browse All Posts