Tallying and Counting Enumerables
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!