user3940837
user3940837

Reputation:

Ruby, An array of hash, convert to single hashmap

What I have is :

{"Key1":[{"key2":"30"},{"key3":"40"}]}

I wish to convert it to :

{"Key1":{"key2":30,"key3":40}}

Upvotes: 0

Views: 77

Answers (2)

Surya
Surya

Reputation: 15992

I'd prefer Stefan's answer as it looks cleaner. Posting this to just show an another approach:

hash = {"key1" => [{"key2" => "30"},{"key3" => "40"}]}

then you can:

hash["key1"] = Hash[hash["key1"].flat_map(&:to_a)]
#=> {"key1"=>{"key2"=>"30", "key3"=>"40"}}

However, I did benchmarking and results were a bit weird:

require 'benchmark'

def with_inject
  hash = {"Key1"=>[{"key2"=>"30"}, {"key3"=>"40"}]}
  hash["Key1"] = hash["Key1"].inject(:merge)
  hash
end

def map_and_flatten
  hash = {"key1" => [{"key2" => "30"},{"key3" => "40"}]}
  hash["key1"] = Hash[hash["key1"].flat_map(&:to_a)]
  hash
end

n = 500000
Benchmark.bm(50) do |x|
  x.report("with_inject     "){ n.times { with_inject } }
  x.report("map_and_flatten "){ n.times { map_and_flatten } }
end

Result with Ruby-1.9.2-p290 -

                        user      system      total        real
with_inject           2.000000   0.000000   2.000000 (  2.008612)
map_and_flatten       2.290000   0.010000   2.300000 (  2.293664)

Result with Ruby-2.0.0-p353 -

                        user      system      total        real
with_inject            2.350000   0.020000   2.370000 (  2.366092)
map_and_flatten        2.420000   0.000000   2.420000 (  2.419962)

Result with Ruby-2-1-2-p95 -

                        user      system      total        real
with_inject            2.180000   0.010000   2.190000 (  2.198437)
map_and_flatten        2.100000   0.000000   2.100000 (  2.104745)

And I'm not sure why map_and_flatten was faster than with_inject in Ruby 2.1.2.

Upvotes: 0

Stefan
Stefan

Reputation: 114138

You can merge multiple hashes:

[{foo: 1}, {bar: 2}, {baz: 3}].inject(:merge)
#=> {:foo=>1, :bar=>2, :baz=>3}

Applied to your hash:

hash = {"Key1"=>[{"key2"=>"30"}, {"key3"=>"40"}]}
hash["Key1"] = hash["Key1"].inject(:merge)
hash #=> {"Key1"=>{"key2"=>"30", "key3"=>"40"}}

Upvotes: 1

Related Questions