In Ruby, given an array in one of the following forms...
[apple, 1, banana, 2]
[[apple, 1], [banana, 2]]
...what is the best way to convert this into a hash in the form of...
{apple => 1, banana => 2}
In Ruby, given an array in one of the following forms...
[apple, 1, banana, 2]
[[apple, 1], [banana, 2]]
...what is the best way to convert this into a hash in the form of...
{apple => 1, banana => 2}
This but here is one way of converting an Array to a Hash:
require "enumerator"
class Array
def to_h
Hash[*enum_with_index.to_a.flatten]
end
end
%w{a b c d}.to_h # => {"a"=>0, "b"=>1, "c"=>2, "d"=>3}
Another sample:
["foo", "bar", "foo1", "bar1","foo2", "bar2"] convert to
{"foo"=>"bar", "foo1"=>"bar1","foo2"=>"bar2"}
def array_to_hash(array)
count = 0
hash = Hash.new
(array.length / 2).times do
hash[array[count]] = array[count+1]
count += 2
end
return hash
end
Simply use Hash[*array_variable.flatten]
For example:
a1 = ['apple', 1, 'banana', 2]
h1 = Hash[*a1.flatten]
puts "h1: #{h1.inspect}"
a2 = [['apple', 1], ['banana', 2]]
h2 = Hash[*a2.flatten]
puts "h2: #{h2.inspect}"
Edit: Saw the responses posted while I was writing, Hash[a.flatten] seems the way to go. Must have missed that bit in the documentation when I was thinking through the response. Thought the solutions that I've written can be used as alternatives if required.
The second form is simpler:
a = [[:apple, 1], [:banana, 2]]
h = a.inject({}) { |r, i| r[i.first] = i.last; r }
a = array, h = hash, r = return-value hash (the one we accumulate in), i = item in the array
The neatest way that I can think of doing the first form is something like this:
a = [:apple, 1, :banana, 2]
h = {}
a.each_slice(2) { |i| h[i.first] = i.last }
Not sure if it's the best way, but this works:
a = ["apple", 1, "banana", 2]
m1 = {}
for x in (a.length / 2).times:
m1[a[x*2]] = a[x*2 + 1]
end
b = [["apple", 1], ["banana", 2]]
m2 = {}
for x,y in b:
m2[x] = y
end
If the numeric values are seq indexes, then we could have simpler ways... Here's my code submission, My Ruby is a bit rusty
input = ["cat", 1, "dog", 2, "wombat", 3]
hash = Hash.new
input.each_with_index {|item, index|
if (index%2 == 0) hash[item] = input[index+1]
}
hash #=> {"cat"=>1, "wombat"=>3, "dog"=>2}
Appending to the answer but using anonymous arrays and annotating: e.g.,
Hash[*("a,b,c,d".split(',').zip([1,2,3,4]).flatten)]
Taking that answer apart, starting from the inside:
"a,b,c,d" is actually a string split on commas into an array zip that together with the following array [1,2,3,4] is an actual array
The intermediate result is [[a,1],[b,2],[c,3],[d,4]]
flatten then transforms that to [a,1,b,2,c,3,d,4] and then [a,1,b,2,c,3,d,4] unrolls that into a,1,b,2,c,3,d,4 which we can use as the arguments to the Hash[] method; i.e., Hash[("a,b,c,d".split(',').zip([1,2,3,4]).flatten)] which yields {"a"=>1, "b"=>2, "c"=>3, "d"=>4}