b1geyedeer
b1geyedeer

Reputation: 101

Converting array of stringified key value pairs to hash in Ruby

I have some key-value pair strings in an array:

array = [ "Name = abc", "Id = 123", "Interest = Rock Climbing" ]

I need to convert it to a hash:

hash = { "Name" => "abc", "Id" => "123", "Interest" => "Rock Climbing" }

I must be doing something wrong because I'm getting weird mappings with my .shift.split resulting in {"Name=abc"=>"Id=123"}.

Upvotes: 3

Views: 6152

Answers (4)

Rahul Patel
Rahul Patel

Reputation: 1424

Try this

array.map {|s| s.split('=')}.to_h

=> {"Name "=>" abc", "Id "=>" 123", "Interest "=>" Rock Climbing"} 

Upvotes: 1

Cary Swoveland
Cary Swoveland

Reputation: 110675

array.each_with_object({}) { |s,h| h.update([s.split(/\s*=\s*/)].to_h) }
  #=> {"Name"=>"abc", "Id"=>"123", "Interest"=>"Rock Climbing"} 

For Ruby versions prior to 2.0 (when Array#to_h was introduced) replace [s.split(/\s*=\s*/)].h with Hash[[s.split(/\s*=\s*/)]]. The steps:

enum = array.each_with_object({})
  #=> #<Enumerator: ["Name = abc", "Id = 123",
  #     "Interest = Rock Climbing"]:each_with_object({})>

We can see the elements of this enumerator by converting it to an array:

enum.to_a
  #=> [["Name = abc", {}], ["Id = 123", {}], ["Interest = Rock Climbing", {}]] 

The first element of enum is passed to the block, the block variables are assigned:

s,h = enum.next
  #=> ["Name = abc", {}] 
s #=> "Name = abc" 
h #=> {} 

and the block calculation is performed:

h.update([s.split(/\s*=\s*/)].to_h)
  #=> h.update([["Name", "abc"]].to_h) 
  #   {}.update({"Name"=>"abc"})
  #   {"Name"=>"abc"}

which is the updated value of h.

The next element of enum passed to the block is:

s,h = enum.next
  #=> ["Id = 123", {"Name"=>"abc"}] 
s #=> "Id = 123" 
h #=> {"Name"=>"abc"} 

h.update([s.split(/\s*=\s*/)].to_h)
  #=> {"Name"=>"abc", "Id"=>"123"}

and so on.

Upvotes: 0

K M Rakibul Islam
K M Rakibul Islam

Reputation: 34338

You can do it this way (using Enumerable#each_with_object):

array.each_with_object({}) do |a, hash|
    key,value = a.split(/\s*=\s*/) # splitting the array items into key and value
    hash[key] = value    # storing key => value pairs in the hash
end
# => {"Name"=>"abc", "Id"=>"123", "Interest"=>"Rock Climbing"}

If you find it little difficult to understand the each_with_object, you can do it in a naive way (Just accumulating the key and values in the result_hash):

result_hash = {}
array.each do |a|
    key,value = a.split(/\s*=\s*/) # splitting the array items into key and value
    result_hash[key] = value # storing key => value pairs in the result_hash
end
result_hash
# => {"Name"=>"abc", "Id"=>"123", "Interest"=>"Rock Climbing"}

Upvotes: 2

Jordan Running
Jordan Running

Reputation: 106027

All you need to do is split each part of the array into a key and value (yielding an array of two-element arrays) and then pass the result to the handy Hash[] method:

arr = [ "Name = abc", "Id = 123", "Interest = Rock Climbing" ]

keys_values = arr.map {|item| item.split /\s*=\s*/ }
# => [ [ "Name", "abc" ],
#      [ "Id", "123" ],
#      [ "Interest", "Rock Climbing" ] ]

hsh = Hash[keys_values]
# => { "Name" => "abc",
#      "Id" => "123",
#      "Interest" => "Rock Climbing" }

Upvotes: 7

Related Questions