[ruby] Array to Hash Ruby

Okay so here's the deal, I've been googling for ages to find a solution to this and while there are many out there, they don't seem to do the job I'm looking for.

Basically I have an array structured like this

["item 1", "item 2", "item 3", "item 4"] 

I want to convert this to a Hash so it looks like this

{ "item 1" => "item 2", "item 3" => "item 4" }

i.e. the items that are on the 'even' indexes are the keys and the items on the 'odd' indexes are the values.

Any ideas how to do this cleanly? I suppose a brute force method would be to just pull out all the even indexes into a separate array and then loop around them to add the values.

This question is related to ruby arrays hashmap

The answer is


This is what I was looking for when googling this:

[{a: 1}, {b: 2}].reduce({}) { |h, v| h.merge v } => {:a=>1, :b=>2}


Or if you have an array of [key, value] arrays, you can do:

[[1, 2], [3, 4]].inject({}) do |r, s|
  r.merge!({s[0] => s[1]})
end # => { 1 => 2, 3 => 4 }

Ruby 2.1.0 introduced a to_h method on Array that does what you require if your original array consists of arrays of key-value pairs: http://www.ruby-doc.org/core-2.1.0/Array.html#method-i-to_h.

[[:foo, :bar], [1, 2]].to_h
# => {:foo => :bar, 1 => 2}

You could try like this, for single array

irb(main):019:0> a = ["item 1", "item 2", "item 3", "item 4"]
  => ["item 1", "item 2", "item 3", "item 4"]
irb(main):020:0> Hash[*a]
  => {"item 1"=>"item 2", "item 3"=>"item 4"}

for array of array

irb(main):022:0> a = [[1, 2], [3, 4]]
  => [[1, 2], [3, 4]]
irb(main):023:0> Hash[*a.flatten]
  => {1=>2, 3=>4}

Just use Hash.[] with the values in the array. For example:

arr = [1,2,3,4]
Hash[*arr] #=> gives {1 => 2, 3 => 4}

All answers assume the starting array is unique. OP did not specify how to handle arrays with duplicate entries, which result in duplicate keys.

Let's look at:

a = ["item 1", "item 2", "item 3", "item 4", "item 1", "item 5"]

You will lose the item 1 => item 2 pair as it is overridden bij item 1 => item 5:

Hash[*a]
=> {"item 1"=>"item 5", "item 3"=>"item 4"}

All of the methods, including the reduce(&:merge!) result in the same removal.

It could be that this is exactly what you expect, though. But in other cases, you probably want to get a result with an Array for value instead:

{"item 1"=>["item 2", "item 5"], "item 3"=>["item 4"]}

The naïve way would be to create a helper variable, a hash that has a default value, and then fill that in a loop:

result = Hash.new {|hash, k| hash[k] = [] } # Hash.new with block defines unique defaults.
a.each_slice(2) {|k,v| result[k] << v }
a
=> {"item 1"=>["item 2", "item 5"], "item 3"=>["item 4"]}

It might be possible to use assoc and reduce to do above in one line, but that becomes much harder to reason about and read.


Enumerator includes Enumerable. Since 2.1, Enumerable also has a method #to_h. That's why, we can write :-

a = ["item 1", "item 2", "item 3", "item 4"]
a.each_slice(2).to_h
# => {"item 1"=>"item 2", "item 3"=>"item 4"}

Because #each_slice without block gives us Enumerator, and as per the above explanation, we can call the #to_h method on the Enumerator object.


a = ["item 1", "item 2", "item 3", "item 4"]
Hash[ a.each_slice( 2 ).map { |e| e } ]

or, if you hate Hash[ ... ]:

a.each_slice( 2 ).each_with_object Hash.new do |(k, v), h| h[k] = v end

or, if you are a lazy fan of broken functional programming:

h = a.lazy.each_slice( 2 ).tap { |a|
  break Hash.new { |h, k| h[k] = a.find { |e, _| e == k }[1] }
}
#=> {}
h["item 1"] #=> "item 2"
h["item 3"] #=> "item 4"

Examples related to ruby

Uninitialized Constant MessagesController Embed ruby within URL : Middleman Blog Titlecase all entries into a form_for text field Ruby - ignore "exit" in code Empty brackets '[]' appearing when using .where find_spec_for_exe': can't find gem bundler (>= 0.a) (Gem::GemNotFoundException) How to update Ruby Version 2.0.0 to the latest version in Mac OSX Yosemite? How to fix "Your Ruby version is 2.3.0, but your Gemfile specified 2.2.5" while server starting Is the server running on host "localhost" (::1) and accepting TCP/IP connections on port 5432? How to update Ruby with Homebrew?

Examples related to arrays

PHP array value passes to next row Use NSInteger as array index How do I show a message in the foreach loop? Objects are not valid as a React child. If you meant to render a collection of children, use an array instead Iterating over arrays in Python 3 Best way to "push" into C# array Sort Array of object by object field in Angular 6 Checking for duplicate strings in JavaScript array what does numpy ndarray shape do? How to round a numpy array?

Examples related to hashmap

How to split a string in two and store it in a field Printing a java map Map<String, Object> - How? Hashmap with Streams in Java 8 Streams to collect value of Map How to convert String into Hashmap in java Convert object array to hash map, indexed by an attribute value of the Object HashMap - getting First Key value The type java.util.Map$Entry cannot be resolved. It is indirectly referenced from required .class files Sort Go map values by keys Print all key/value pairs in a Java ConcurrentHashMap creating Hashmap from a JSON String