Converting an Array of Hashes to One Hash in Ruby

Array of hashes to hash

You may use

a.reduce Hash.new, :merge

which directly yields

{:a=>:b, :c=>:d}

Note that in case of collisions the order is important. Latter hashes override previous mappings, see e.g.:

[{a: :b}, {c: :d}, {e: :f, a: :g}].reduce Hash.new, :merge   # {:a=>:g, :c=>:d, :e=>:f}

Convert array of hashes to single hash with values as keys

This should do what you want

countries.each_with_object({}) { |country, h| h[country[:country].to_sym] = country[:cost] }
=> {:england=>12.34, :scotland=>56.78}

Convert array-of-hashes to a hash-of-hashes, indexed by an attribute of the hashes

Ruby <= 2.0

> Hash[api_response.map { |r| [r[:id], r] }]
#=> {1=>{:id=>1, :foo=>"bar"}, 2=>{:id=>2, :foo=>"another bar"}}

However, Hash::[] is pretty ugly and breaks the usual left-to-right OOP flow. That's why Facets proposed Enumerable#mash:

> require 'facets'
> api_response.mash { |r| [r[:id], r] }
#=> {1=>{:id=>1, :foo=>"bar"}, 2=>{:id=>2, :foo=>"another bar"}}

This basic abstraction (convert enumerables to hashes) was asked to be included in Ruby long ago, alas, without luck.

Note that your use case is covered by Active Support: Enumerable#index_by

Ruby >= 2.1

[UPDATE] Still no love for Enumerable#mash, but now we have Array#to_h. It creates an intermediate array, but it's better than nothing:

> object = api_response.map { |r| [r[:id], r] }.to_h

How can I convert a ruby array of hashes into a single hash?

arr = [{"name"=>"apple",  "value"=>"red"},
{"name"=>"banana", "value"=>"yellow"},
{"name"=>"grape", "value"=>"purple"}]

Hash[arr.map { |h| [h["name"].to_sym , h["value"]] }]
#=> {:apple=>"red", :banana=>"yellow", :grape=>"purple"}

With Ruby 2.1+

arr.map { |h| [h["name"].to_sym , h["value"]] }.to_h
#=> {:apple=>"red", :banana=>"yellow", :grape=>"purple"}

Converting an array of hashes to ONE hash in Ruby

I think the key to the solution is Hash[], which will create a Hash based on an array of key/values, i.e.

Hash[[["key1", "value1"], ["key2", "value2"]]]
#=> {"key1" => "value1", "key2" => "value2"}

Just add a set of map, and you have a solution!

result = [
{"id_t"=>["1"], "transcript_t"=>["I am a transcript ONE"]},
{"id_t"=>["2"], "transcript_t"=>["I am a transcript TWO"]},
{"id_t"=>["3"], "transcript_t"=>["I am a transcript THREE"]}
]
Hash[result.map(&:values).map(&:flatten)]

Convert array of hash to single hash in ruby

a.each_with_object({}) {|obj , hash| hash.merge!(Hash[obj[:id], Hash["active_accounts",obj[:active_accounts]]])}

# {5=>{"active_accounts"=>3}, 1=>{"active_accounts"=>6}}

Hope it helps.

Ruby Array of hashes to a Hash

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"}}

How can I transpose array of hashes in ruby

Something like this might do the job:

keys = input.map { |hash| hash['Key'] }.uniq
result = Hash.new { |result, id| result[id] = {} }
input.each { |hash| result[hash['ID']].merge!(hash['Key'] => hash['Value']) }
result.default = nil # optional: remove the default value

result.each do |id, hash|
(keys - hash.keys).each { |key| hash[key] = '' }
hash['ID'] = id
end

result.values
#=> [{"Field A"=>"123", "Field B"=>"333", "Field C"=>"555", "Field D"=>"", "ID"=>"100"},
# {"Field A"=>"789", "Field B"=>"999", "Field D"=>"444", "Field C"=>"", "ID"=>"200"}]

If you're certain values are never falsy you can replace:

(keys - hash.keys).each { |key| hash[key] = '' }
# with
keys.each { |key| hash[key] ||= '' }

I first create a hash result to save the resulting hashes, I set the value to defaults to a new hash. Then I get the correct hash based upon ID and merge the key-value pairs into the hash. Lastly I add the missing keys to the hashes and set their values to an empty string and add the ID under which the hash is saved to the hash.

note: If your input array contains duplicate key-value pairs, the last one will be used. For example, say both {"ID"=>"100", "Key"=>"Field A", "Value"=>"123"} and {"ID"=>"100", "Key"=>"Field A", "Value"=>"456"} are present. Then "Field A" => "456" will be set, since it's the latter of the two.

Convert hash to array of hashes

Leveraging Array#transpose and Array#to_h

keys = list.keys
list.values.transpose.map { |v| keys.zip(v).to_h }

Convert array of hashes to array

a=[{:code=>"404"}, {:code=>"302"}, {:code=>"200"}] 
puts a.map{|x|x.values}.flatten.inspect

output

["404", "302", "200"]


Related Topics



Leave a reply



Submit