.group_by - The Art of Clean Up
March 12th 2016
You may call the Swiss comedian & artist Ursus Wehrli slightly "compulsary obsessive".
He published a photo-book "The Art of Clean Up" in which he takes everyday objects or life situations and "tidies them up".
Ursus has created (and reworked) some great pieces of art, but it took probably hours of dedicated work to get the results he was looking for. If only he had some basic understanding of Ruby's enumerable .group_by
.
In this blogpost I will introduce you to the .group_by
method: a powerful enumerable method to manipulate objects in Ruby.

Introduction
The .group_by
operation will group all the elements in a "collection object" by something that we want it to group by. As Ursus did in his art, we may want to group the objects based on their color, their size, shape etc. The options are countless!
This method excels at tidying up large data-sets. You can probably imagine useful applications of this method in your direct environment:
- Grouping all employees in a company per responsible manager
- Grouping the items in a webshop per logical category (mens, womens, kids etc.)
- Grouping the invite list per RSVP status
- Etc.
How it works
The .group_by
operation on an enumerable object will group all elements of that object by equal outcomes of a logical test (provided by a code-block) and return a hash.
So all object element that return the same value when ran by a code-block will be assigned to the same group. For each "new" outcome, a new hash-key is created to host equal outcomes.
The syntax is structured in following way: group_by { |obj| block } → a_hash
Some examples:
-
Grouping by quotient:
(1..6).group_by {|i| i%3} #=> {0=>[3, 6], 1=>[1, 4], 2=>[2, 5]}
-
Grouping by first letter:
countries = ["United States", "Brazil", "Canada", "Belgium", "Rwanda"]
grouped_by_first_letter = countries.group_by { |s| s[0] }
#=> {B=>[Belgium, Brazil], C=>[Canada], R=>[Rwanda], U=>[United States]} -
Grouping by category:
groceries = {
"apple"=>"fruit",
"lettuce"=>"vegetable",
"tomato"=>"vegetable",
"pineapple"=>"fruit",
"orange"=>"fruit",
"banana"=>"fruit",
"cucumber"=>"vegetable",
"kiwi"=>"fruit"
}
item_by_category = groceries.group_by{|k,v| v}
#=>{"fruit"=>[["apple", "fruit"], ["pineapple", "fruit"], ["orange", "fruit"], ["banana", "fruit"], ["kiwi", "fruit"]], "vegetable"=>[["lettuce", "vegetable"], ["tomato", "vegetable"], ["cucumber", "vegetable"]]}