Stephen C
Stephen C

Reputation: 863

Group Array of Hashes by Key followed by values

Assuming I have the following dataset

[ 
  {
    :name => "sam",
    :animal => "dog",
    :gender => "male"
  }, {
    :name => "max",
    :animal => "cat",
    :gender => "female"
  }, {
    :name => "joe",
    :animal => "snake",
    :gender => "male"
  }    
]

How would you group the array of hashes to:

{
  :name => ["sam", "max", "joe"]
  :animal => ["dog", "cat", "snake"]
  :gender => ["male", "female", "male"]
}

I've read similar articles such as this and Group array of hashes by key

However, most examples return the values as increment counts where I'm looking for actual separate values.

My attempt

keys = []
values = []

arr.each do |a|
  a.each do |k, v|
    keys << k
    #this is where it goes wrong and where I'm stuck at
    values << v
  end
end

keys = keys.uniq

I understand where I went wrong is how I'm trying to segment the values. Any direction would be appreciated!

Upvotes: 5

Views: 850

Answers (2)

fl00r
fl00r

Reputation: 83680

few more approaches

data.each_with_object({}){ |i,r| i.each{ |k,v| (r[k] ||= []) << v } }
data.flat_map(&:to_a).each_with_object({}){ |(k,v), r| (r[k] ||= []) << v }
data.flat_map(&:to_a).group_by(&:first).inject({}){ |r, (k,v)| r[k] = v.map(&:last); r }

Upvotes: 1

Aleksei Matiushkin
Aleksei Matiushkin

Reputation: 121000

input.reduce { |e, acc| acc.merge(e) { |_, e1, e2| [*e2, *e1] } }
#⇒ {:name=>["sam", "max", "joe"],
#   :animal=>["dog", "cat", "snake"],
#   :gender=>["male", "female", "male"]}

Upvotes: 4

Related Questions