The group_by method from Ruby’s Enumerable mixin (and compared with Scala)

A few weeks ago I wrote about the groupBy method from Scala’s collection library. Today I will port those example to Ruby for which there is also such a method, just with s slightly different name (group_by instead of groupBy).

For the idea behind the method, see the post about Scala’s version. Here I will put the Scala code from the other post and show the equivalent code for Ruby next to it.
Note: I’ve used Ruby 1.9.2p290 for all examples.

1st Example:

Here we group an Array (in Scala List) of strings (with names of different bird species) by their first name.


val birds = List("Golden Eagle", "Gyrfalcon", "American Robin", 
                 "Mountain BlueBird", "Mountain-Hawk Eagle")
val groupedByFirstLetter = birds.groupBy(_.charAt(0))


birds = ["Golden Eagle", "Gyrfalcon", "American Robin", 
            "Mountain BlueBird", "Mountain-Hawk Eagle"]
grouped_by_first_letter = birds.group_by { |s| s[0] }

# {G=>[Golden Eagle, Gyrfalcon], A=>[American Robin],
# M=>[Mountain BlueBird, Mountain-Hawk Eagle]}

The value of the resulting Hash is shown in the comment. The line breaks were added by me to make it more readable. They are not part of the result.

2nd Example:

Here we group and Array (in Scala List) of strings by their length.


val cats = List("Tiger", "Lion", "Puma", "Leopard",
                  "Jaguar", "Cheetah", "Bobcat")
val groupedByLength = cats.groupBy(_.length)


cats = ["Tiger", "Lion", "Puma", "Leopard", "Jaguar",
        "Cheetah", "Bobcat"]
grouped_by_length = cats.group_by { |cat| cat.length }

#{5=>[Tiger], 4=>[Lion, Puma], 7=>[Leopard, Cheetah], 6=>[Jaguar, Bobcat]}

3rd Example:

Here we group some raptor (birds of prey) species by their kind. Everything that is not an Eagle or Falcon will be “Unknown”.


val raptors = List("Golden Eagle", "Bald Eagle", "Prairie Falcon",
                      "Peregrine Falcon", "Harpy Eagle", "Red Kite")
val kinds = raptors.groupBy {
   case bird if bird.contains(Eagle) => eagle
   case bird if bird.contains(Falcon) => falcon
   case _ => unknown


raptors = ["Golden Eagle", "Bald Eagle", "Prairie Falcon", "Peregrine Falcon", 
           "Harpy Eagle", "Red Kite"]

kinds = raptors.group_by do |species| 
 case species
    when /.*Eagle.*/
  when /.*Falcon.*/

# {Eagle=>[Golden Eagle, Bald Eagle, Harpy Eagle], 
# Falcon=>[Prairie Falcon, Peregrine Falcon], unknown=>[Red Kite]}

4th Example

Here we take an Array (List in Scala) of String and group them by the number of occurrences in the Array.


val words = List("one", "two", "one", "three", "four", "two", "one")
val counts = words.groupBy(w => w).mapValues(_.size)


words = ["one", "two", "one", "three", "four", "two", "one"]
count = words.group_by { |w| w }.inject({}) do |tmphash, (k,v)|
      tmphash[k] = v.size

# {one=>3, two=>2, three=>1, four=>1}

Ruby’s Hash class does not have a mapValues method like Scala’s Maps do (at least I couldn’t find one in the standard library) , so I used inject instead which is very similar to foldLeft in Scala. This is not as elegant as mapValues but get’s the job done as well.


As you can see the Ruby version of the group_by method is as easy to use as Scala’s version. Both Ruby and Scala provide a lot of great tools to work with collections. Scala’s collection library is much bigger than Ruby’s standard collections, though. Scala supports many more data structures and also a lot of immutable data structures because Scala also encourages functional programming (whereas Ruby is mostly only OOP).

No matter what language you use, learn as much about the available collections in the standard library (or available open source packages) as possible because this will save you a lot of time when using those languages.