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

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

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 B. http://agileconsultingllc.com
[email protected]

Sam K. 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

On Oct 19, 2:01 pm, Sam K. [email protected] 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

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 Behalf Of Sam K.:

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

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

The above method should return an array of arrays grouped by age.
h[ yield( x ) ] += [ x ]
}
h.values
end
end

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

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

Regards, Morton