Gary S. Weaver
Gary S. Weaver

Reputation: 8096

How to collect properties/attributes of an object as a hash of key to array of values?

If you have an array of objects with two attributes, a and b, e.g.

$ irb
2.1.3 :001 > D = Struct.new(:a, :b)
 => D 
2.1.3 :002 > data = [] << D.new('e', 'f') << D.new('g', 'h') << D.new('e', 'i') << D.new('j', 'h')
 => [#<struct D a="e", b="f">, #<struct D a="g", b="h">, #<struct D a="e", b="i">, #<struct D a="j", b="h">]

And want to produce from that a hash where the attribute a is the key and attribute b is a collection of values, e.g.

{"e"=>["f", "i"], "g"=>["h"], "j"=>["h"]}

What is a simple way to do that in Ruby?

(I've shared my answer that uses each_with_object, but maybe there is a simpler or clearer way.)

Upvotes: 0

Views: 218

Answers (2)

rohit89
rohit89

Reputation: 5773

Another way of doing it is

1.9.3-p327 :023 > hash = data.inject(Hash.new {|h, k| h[k] = []}) {|h, i| h[i.a] << i.b; h}
 => {"e"=>["f", "i"], "g"=>["h"], "j"=>["h"]}

Upvotes: 0

Gary S. Weaver
Gary S. Weaver

Reputation: 8096

This can be done with each_with_object:

2.1.3 :003 > data.each_with_object({}) {|p, h| (h[p.a] ||= []) << p.b}
 => {"e"=>["f", "i"], "g"=>["h"], "j"=>["h"]} 

Upvotes: 1

Related Questions