What is the best way to convert an array to a hash in Ruby What is the best way to convert an array to a hash in Ruby ruby ruby

What is the best way to convert an array to a hash in Ruby


Simply use Hash[*array_variable.flatten]

For example:

a1 = ['apple', 1, 'banana', 2]h1 = Hash[*a1.flatten(1)]puts "h1: #{h1.inspect}"a2 = [['apple', 1], ['banana', 2]]h2 = Hash[*a2.flatten(1)]puts "h2: #{h2.inspect}"

Using Array#flatten(1) limits the recursion so Array keys and values work as expected.


NOTE: For a concise and efficient solution, please see Marc-André Lafortune's answer below.

This answer was originally offered as an alternative to approaches using flatten, which were the most highly upvoted at the time of writing. I should have clarified that I didn't intend to present this example as a best practice or an efficient approach. Original answer follows.


Warning! Solutions using flatten will not preserve Array keys or values!

Building on @John Topley's popular answer, let's try:

a3 = [ ['apple', 1], ['banana', 2], [['orange','seedless'], 3] ]h3 = Hash[*a3.flatten]

This throws an error:

ArgumentError: odd number of arguments for Hash        from (irb):10:in `[]'        from (irb):10

The constructor was expecting an Array of even length (e.g. ['k1','v1,'k2','v2']). What's worse is that a different Array which flattened to an even length would just silently give us a Hash with incorrect values.

If you want to use Array keys or values, you can use map:

h3 = Hash[a3.map {|key, value| [key, value]}]puts "h3: #{h3.inspect}"

This preserves the Array key:

h3: {["orange", "seedless"]=>3, "apple"=>1, "banana"=>2}


The best way is to use Array#to_h:

[ [:apple,1],[:banana,2] ].to_h  #=> {apple: 1, banana: 2}

Note that to_h also accepts a block:

[:apple, :banana].to_h { |fruit| [fruit, "I like #{fruit}s"] }   # => {apple: "I like apples", banana: "I like bananas"}

Note: to_h accepts a block in Ruby 2.6.0+; for early rubies you can use my backports gem and require 'backports/2.6.0/enumerable/to_h'

to_h without a block was introduced in Ruby 2.1.0.

Before Ruby 2.1, one could use the less legible Hash[]:

array = [ [:apple,1],[:banana,2] ]Hash[ array ]  #= > {:apple => 1, :banana => 2}

Finally, be wary of any solutions using flatten, this could create problems with values that are arrays themselves.