Posted over 3 years ago. Visible to the public.

Custom Ruby method Enumerable#count_by (use for quick statistics)

I frequently find myself needing a combination of group_by, count and sort for quick statistics. Here's a method on Enumerable that combines the three:

Copy
module Enumerable def count_by(&block) list = group_by(&block) .map { |key, items| [key, items.count] } .sort_by(&:last) Hash[list] end end # Returns a Hash of { key => count } pairs (see below)

Usage examples

  • Number of email addresses by domain:
Copy
> User.all.count_by { |user| user.email.sub /^.*@/, '' } => { "sina.cn"=>2, ..., "hotmail.com"=>128, "gmail.com"=>153}
  • Number of new users per day: User.all.count_by { |user| user.created_at.to_date }
  • Number of articles per brand: Article.all.count_by &:brand

Note that the last simple example can also be achieved with Rails internals: Article.group(:brand).count. This translates to SQL, so it executes fast. However, grouping is restricted to columns (attributes). Using #count_by gives you the full flexibility of Ruby.

More tools

If you need further options, here's a "toolbox" of chainable method invocations:

Copy
list .group_by { |item| item.id } # Group .map { |key, items| [key, items.count] } # Count .select { |key, count| count > 10 } # Filter .sort_by(&:last) # Sort ASC .reverse # Sort DESC .each { |key, count| puts "#{count.to_s.rjust(6)} #{key}" } # Print

Wrap the result in Hash[...] to turn a list-of-pairs into a Hash.

makandra has been working exclusively with Ruby on Rails since 2007. Our laser focus on a single technology has made us a leader in this space.

Owner of this card:

Avatar
Dominik Schöler
Last edit:
10 months ago
by Dominik Schöler
About this deck:
We are makandra and do test-driven, agile Ruby on Rails software development.
License for source code
Posted by Dominik Schöler to makandra dev
This website uses short-lived cookies to improve usability.
Accept or learn more