What's the ruby way of grouping elements of an array?

Hi,

I thought this would be a common need but I couldn't find a method.

Let's say I have an array of objects.
I want to group the elements by a property of objects.

people.group_by do |person|
  person.age
end

The above method should return an array of arrays grouped by age.

What's the ruby way for this case?
I think I can implement it but I am sure that a good way already exists.

Thanks.

Sam

···

--
Posted via http://www.ruby-forum.com/.

ActiveSupport (part of Rails, but usable separately as a gem) does this:

http://api.rubyonrails.org/classes/Enumerable.html#M001111
     # File vendor/rails/activesupport/lib/active_support/core_ext/enumerable.rb, line 17
17: def group_by
18: inject({}) do |groups, element|
19: (groups[yield(element)] ||= ) << element
20: groups
21: end
22: end

This returns a hash of age=>[people], but you could deal with that by .values or sorting or whatever makes the most sense for your application.

-Rob

Rob Biedenharn http://agileconsultingllc.com
Rob@AgileConsultingLLC.com

···

On Oct 19, 2007, at 3:01 PM, Sam Kong wrote:

Hi,

I thought this would be a common need but I couldn't find a method.

Let's say I have an array of objects.
I want to group the elements by a property of objects.

people.group_by do |person|
  person.age
end

The above method should return an array of arrays grouped by age.

What's the ruby way for this case?
I think I can implement it but I am sure that a good way already exists.

Thanks.

Sam
--
Posted via http://www.ruby-forum.com/\.

Sam Kong wrote:

The above method should return an array of arrays grouped by age.

What's the ruby way for this case?
I think I can implement it but I am sure that a good way already exists.

Thanks.

Sam

If you require 'action_pack' you get group_by() for free

Array.new(20) {Kernel.rand(20)}.group_by {|age| age > 10}

=> {false=>[9, 5, 3, 6, 0, 8, 3, 4, 9, 2, 0, 0, 10, 1], true=>[15, 13,
18, 12, 13, 14]}

hth

ilan

···

--
Posted via http://www.ruby-forum.com/\.

It's pretty simple.

class Array
  def group_by
    h = Hash.new{ }
    each{|x|
      h[ yield( x ) ] += [ x ]
    }
    h.values
  end
end

p %w(a little while ago I heard the tittering of a mouse).
  group_by{|s| s.size }

···

On Oct 19, 2:01 pm, Sam Kong <sam.s.k...@gmail.com> wrote:

Hi,

I thought this would be a common need but I couldn't find a method.

Let's say I have an array of objects.
I want to group the elements by a property of objects.

people.group_by do |person|
  person.age
end

The above method should return an array of arrays grouped by age.

What's the ruby way for this case?
I think I can implement it but I am sure that a good way already exists.

Thanks.

Sam

On Behalf Of Sam Kong:
# people.group_by do |person|
# person.age
# end
# The above method should return an array of arrays
# grouped by age. What's the ruby way for this case?
# I think I can implement it but I am sure that a good
# way already exists.

as you've said (and as others have offered), you'll have to implement it or use another lib/gem.

if you can wait for ruby2 (or use 1.9), the group_by and symbol's to_proc is a good combi. eg,

people.group_by{|person| person.age}

...
or

people.group_by(& :age)

...

RUBY_VERSION

=> "1.9.0"

btw, group_by returns hash of arrays

kind regards -botp

That's good, but I think the following modification makes it a little better:

<code>
class Array
    def group_by
       h = Hash.new { |h, k| h[k] = }
       each { |item| h[yield(item)] << item }
       h.values
    end
end
</code>

Regards, Morton

···

On Oct 19, 2007, at 9:05 PM, William James wrote:

On Oct 19, 2:01 pm, Sam Kong <sam.s.k...@gmail.com> wrote:

I thought this would be a common need but I couldn't find a method.

Let's say I have an array of objects. I want to group the elements by a property of objects.

people.group_by do |person|
  person.age
end

The above method should return an array of arrays grouped by age.

What's the ruby way for this case? I think I can implement it but I am sure that a good way already exists.

It's pretty simple.

class Array
  def group_by
    h = Hash.new{ }
    each{|x|
      h[ yield( x ) ] += [ x ]
    }
    h.values
  end
end