Niro
Niro

Reputation: 443

Ruby Array of hashes to a Hash

I have an array that looks something like this

array = [{ a: 123, b: 'foo', c: 'bar' }, { a: 456, b: 'baz', c: 'qux' }]

I would like to convert this to a hash whose keys are the values of :a in the hashes in array, and whose values consist of hashes with :b and :c.

{ 123 => { b: 'foo', c: 'bar' }, 456 => { b: 'baz', c: 'qux' } }

Is this doable using ruby?

Upvotes: 0

Views: 452

Answers (4)

Ashik Salman
Ashik Salman

Reputation: 1879

Using Hash#select method.

array.map { |v| [v.fetch(:a), v.select { |k,_| k != :a }] }.to_h

Exact :a, :b & :c

array.map { |v| [v.fetch(:a), v.select { |k,_| [:b, :c].include? k }] }.to_h

Output

{123=>{:b=>"foo", :c=>"bar"}, 456=>{:b=>"baz", :c=>"qux"}} 

Upvotes: 0

Cary Swoveland
Cary Swoveland

Reputation: 110675

Assuming that all elements of array (hashes) have a key :a and that array cannot be mutated, use Hash#reject:

array.each_with_object({}) { |g,h| h[g[:a]] = g.reject { |k,_| k == :a } }
  #=> {123=>{:b=>"foo", :c=>"bar"}, 456=>{:b=>"baz", :c=>"qux"}}

Upvotes: 0

sawa
sawa

Reputation: 168101

array.each_with_object({}){|e, h| e = e.dup; h[e.delete(:a)] = e}
# => {123=>{:b=>"foo", :c=>"bar"}, 456=>{:b=>"baz", :c=>"qux"}}

If you don't care about side effects:

array.each_with_object({}){|e, h| h[e.delete(:a)] = e}
# => {123=>{:b=>"foo", :c=>"bar"}, 456=>{:b=>"baz", :c=>"qux"}}

Upvotes: 2

shouya
shouya

Reputation: 3083

I'm not sure what problem you're trying to solve. This is what I come out with:

def group_by_key(array, key)
  array.map { |x| [x.delete(key), x] }.to_h
end

It works good on your example:

array = [{ a: 123, b: 'foo', c: 'bar' }, { a: 456, b: 'baz', c: 'qux' }]
group_by_key(array, :a)
#=> {123=>{:b=>"foo", :c=>"bar"}, 456=>{:b=>"baz", :c=>"qux"}}

Upvotes: 1

Related Questions