This was the tip of the week in the Feb 18, 2021 Ruby Weekly Newsletter.


Counting is one of the many things computers do better than humans. Ruby’s Enumerable#tally, introduced in Ruby 2.7, makes counting even more straightforward.

It counts the occurences of each element in a collection, and returns a hash whose keys are all of the distinct elements in the collection, and whose values are the number of times each key appears.

Pre Ruby 2.7, if we wanted a hash which gave us counts of the elements in a collection, there were a few less straightforward ways we could do it. One example of code we might have written is:

[1, 2, 0, 2, 2, 3, 2, 1, 3].group_by(&:itself).transform_values(&:size)
=> {1=>2, 2=>4, 0=>1, 3=>2}

Luckily, we now have Enumerable#tally which makes this same functionality cleaner to write and easier to read. Let’s look at a couple of examples:

[1, 2, 0, 2, 2, 3, 2, 1, 3].tally
=> {1=>2, 2=>4, 0=>1, 3=>2}

%w(r u b y w e e k l y).tally
=> {"r"=>1, "u"=>1, "b"=>1, "y"=>2, "w"=>1, "e"=>2, "k"=>1, "l"=>1}

As we can see, the keys are the elements in each array, and the values are their counts. If we were only interested in the number of times a specific element appeared in an Enumerable, we could also use Enumerable#count which takes an element as a parameter. For example:

[1, 2, 0, 2, 2, 3, 2, 1, 3].count(1)
=> 2

[1, 2, 0, 2, 2, 3, 2, 1, 3].count(5)
=> 0

Hopefully Enumerable#tally and Enumerable#count help with any Ruby counting needs!