Recently, I’ve had quite a popular problem to solve: count the occurences of the given item in a collection. There are few ways to solve this problem - starting from using Enumerable#inject or Enumerable#each_with_object with an empty hash as an accumulator value and writing a code looking like this:

collection . each_with_object ({}) { | item , accum | accum [ item ] = accum [ item ]. to_i + 1 }

through a bit smarter way and taking advantage of the default hash value:

collection . each_with_object ( Hash . new ( 0 )) { | item , accum | accum [ item ] = accum [ item ] + 1 }

All these solutions look quite nice; however, there is one that looks particularly beautiful.

The Aesthetics of Ruby

An interesting way of solving this problem is by using Enumerable#group_by - we can simply group elements by themselves and count the occurences of each item. Here is one way to implement it:

collection . group_by { | item | item }. map { | key , value | [ key , value . count ] }. to_h

However, it doesn’t look that great, especially for Ruby standard. We could do better. Ruby 2.4 adapted a very useful core extension from ActiveSupport: Hash#transform_values . Thanks to this addition, we could rewrite that to the following code:

collection . group_by { | item | item }. transform_values ( & :count )

Looks much better, but group_by { |item| item } could still be improved. Is there anything in Ruby that could help us in such case?

It turns out there is! One of the additions in Ruby 2.2 was Kernel#itself , which simply returns self. It might sound like an odd idea to introduce such method, but this is exactly something that we need:

collection . group_by ( & :itself ). transform_values ( & :count )

This code looks just beautiful.

Wrapping up