Although it's already in Ruby itself, this is how `Enumerable#group_by` works.

This article is quite old.Time flies when you're having fun. I've been writing for my blog for a long time. Stuff changes fast, especially in the Ruby world. That's why I've put this warning on old posts. The article might still be valid, though.

Monkey Patch of the Month: group_by

A while back, I talked about new additions to ActiveSupport. And now, I have a confession to make: I like monkey patches! At least, as long as they're short and self-explanatory.

I got a few of them lying around, so I am going to post one every month. I also welcome your favorite monkey patch, which you can email me.

So, the first one: group_by. This method groups arrays of objects by the result of the block provided and puts the result into a hash.

class Array
  # Turns an array into a hash, using the results of the block as keys for the
  # hash.
  #
  #   [1, 2, 3, 4].group_by(&:odd?)
  #   # => {true=>[1, 3], false=>[2, 4]}
  #
  #   ["One", "Two", "three"].group_by {|i| i[0,1].upcase }
  #   # => {"T"=>["Two", "three"], "O"=>["One"]}
  def group_by
    hash = Hash.new { |hash, key| hash[key] = [] }
    each { |item| hash[yield(item)] << item }
    hash
  end
end

No piece of code is complete without tests, so this is it:

class ArrayExtGroupingTests < Test::Unit::TestCase

  def test_group_by
    assert_equal {true=>[1, 3], false=>[2, 4]}, [1, 2, 3, 4].group_by(&:odd?)
    assert_equal {"T"=>["Two", "three"], "O"=>["One"]}, ["One", "Two", "three"].group_by {|i| i[0,1].upcase }
  end

end

Update

Silly me, this one is already in Ruby itself. Anyway, this is how it works under the cover...

comments powered byDisqus