ssk
October 19, 2007, 9:01pm
1
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
ssk
October 19, 2007, 9:18pm
2
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]
ssk
October 19, 2007, 10:50pm
3
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
ssk
October 20, 2007, 3:05am
4
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 }
ssk
October 22, 2007, 5:22am
5
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
ssk
October 21, 2007, 1:18am
6
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