Three ways to use Ruby's group_by

Ruby’s #group_by method provides a way to (wait for it) group things by some arbitrary property. It’s part of the Enumerable module, so you can generally use it anywhere you’d be using #each or some iteration. To use #group_by, you first need to know two things:

  • The collection of objects that needs grouping (e.g., an array)
  • The rule by which you want to group those objects

#group_by returns a hash where the keys are defined by our grouping rule, and the values are the corresponding objects from our original collection.

Now let’s look at three examples of #group_by in action!

##Example #1: Grouping strings

  • The collection: last names stored as strings in an array
  • The rule: group names according to the first letter
# Create a list of names
names = ["Ripley", "McClane", "Ryerson", "Murphy"]
# group by first letter
names_by_letter = names.group_by { |name| name[0] }

#{
#    "R" => [
#        [0] "Ripley",
#        [1] "Ryerson"
#    ],
#    "M" => [
#        [0] "McClane",
#        [1] "Murphy"
#    ]
#}

##Example #2: Grouping integers

  • The collection: an array of 50 random integers between 1 and 99
  • The rule: group integers into 5 bins (e.g, 1-19, 20-39…)
# generate random numbers
numbers = (1..99).to_a.sample 50
# group by quotient (number divided by 20)
data.group_by { |number| number / 20 }

#{
#    3 => [
#        [0] 78,
#        [1] 61,
#        [2] 67,
#        [3] 65,
#        [4] 68,
#        [5] 71,
#        [6] 76,
#        [7] 70,
#        [8] 64,
#        [9] 60
#    ],
#    1 => [
#        [ 0] 24,
#        [ 1] 39,
#        [ 2] 28,
#        [ 3] 20,
#        [ 4] 26,
#        [ 5] 31,
#        [ 6] 29,
#        [ 7] 35,
#        [ 8] 32,
#        [ 9] 33,
#        [10] 30
#    ],
#    2 => [
#        [0] 49,
#        [1] 57,
#        [2] 46,
#        [3] 51,
#        [4] 52,
#        [5] 42,
#        [6] 55,
#        [7] 58
#    ],
#    4 => [
#        [0] 84,
#        [1] 80,
#        [2] 93,
#        [3] 91,
#        [4] 92,
#        [5] 86
#    ],
#    0 => [
#        [ 0] 10,
#        [ 1] 9,
#        [ 2] 13,
#        [ 3] 14,
#        [ 4] 8,
#        [ 5] 17,
#        [ 6] 18,
#        [ 7] 11,
#        [ 8] 2,
#        [ 9] 7,
#        [10] 4,
#        [11] 3,
#        [12] 19,
#        [13] 15,
#        [14] 5
#    ]
#}

##Example #3: Grouping various objects

  • The collection: an array of various classes of objects
  • The rule: group objects by class
# Create a list of objects 
array_of_fun = ["Bob", 89, [1, 2, 3], Hash.new, (0..10).to_a, "Gene", 5]
# group objects by class
array of fun.group_by { |thing| thing.class }

#{
#     String < Object => [
#        [0] "Bob",
#        [1] "Gene"
#    ],
#    Fixnum < Integer => [
#        [0] 89,
#        [1] 5
#    ],
#      Array < Object => [
#        [0] [
#            [0] 1,
#            [1] 2,
#            [2] 3
#        ],
#        [1] [
#            [ 0] 0,
#            [ 1] 1,
#            [ 2] 2,
#            [ 3] 3,
#            [ 4] 4,
#            [ 5] 5,
#            [ 6] 6,
#            [ 7] 7,
#            [ 8] 8,
#            [ 9] 9,
#            [10] 10
#        ]
#    ],
#       Hash < Object => [
#        [0] {}
#    ]
#}

These are pretty contrived examples, but when combined with other methods, #group_by can be a handy way to get your objects in order. Now go get grouping!