Reputation: 13
I want to loop through a multi-dimensional array:
array = [[1,2,3,4,5], [6,7,8,9,10]]
and create a hash with keys from a another array:
keyValues = "one","two","three","four","five"
I have the following code to do this:
hash = Hash.new
multiArray = Array.new
array.each do |values|
keyValues.each do |key|
i = keyValues.index(key)
hash[key] = values[i]
end
puts hash
multiArray << hash
end
puts multiArray
The puts hash
outputs:
{"one"=>1, "two"=>2, "three"=>3, "four"=>4, "five"=>5}
{"one"=>6, "two"=>7, "three"=>8, "four"=>9, "five"=>10}
and the final multiArray
is:
{"one"=>6, "two"=>7, "three"=>8, "four"=>9, "five"=>10}
{"one"=>6, "two"=>7, "three"=>8, "four"=>9, "five"=>10}
I can't figure out why I'm not getting:
{"one"=>1, "two"=>2, "three"=>3, "four"=>4, "five"=>5}
for the final multiArray
.
Upvotes: 0
Views: 175
Reputation: 12578
First, install y_support
gem (gem install y_support
). It defines Array#>>
operator useful for constructing hashes:
require 'y_support/core_ext/array'
[ :a, :b, :c ] >> [ 1, 2, 3 ]
#=> {:a=>1, :b=>2, :c=>3}
With it, your job can be done like this:
array = [1,2,3,4,5], [6,7,8,9,10]
key_values = ["one","two","three","four","five"]
multi_array = array.map { |a| key_values >> a }
#=> [{"one"=>1, "two"=>2, "three"=>3, "four"=>4, "five"=>5},
{"one"=>6, "two"=>7, "three"=>8, "four"=>9, "five"=>10}]
Upvotes: 0
Reputation: 110685
Now that @August has identified the problem with your code, I'd like to suggest a compact, Ruby-like way to obtain the result you want.
Code
def make_hash(array, key_values)
array.map { |a| key_values.zip(a).to_h }
end
Example
array = [[1,2,3,4,5], [6,7,8,9,10]]
key_values = ["one","two","three","four","five"]
make_hash(array, key_values)
#=> [{"one"=>1, "two"=>2, "three"=>3, "four"=>4, "five"=>5},
# {"one"=>6, "two"=>7, "three"=>8, "four"=>9, "five"=>10}]
Explanation
The first value passed into the block by Enumerable#map is:
a = [1,2,3,4,5]
so we have
b = key_values.zip(a)
#=> [["one", 1], ["two", 2], ["three", 3], ["four", 4], ["five", 5]]
b.to_h
#=> {"one"=>1, "two"=>2, "three"=>3, "four"=>4, "five"=>5}
For Ruby versions < 2.0 (when Array.to_h was introduced), we'd have to write Hash(b)
rather than b.to_h
.
Similarly, the second value passed to the block is:
a = [6,7,8,9,10]
so
key_values.zip(a).to_h
#=> {"one"=>6, "two"=>7, "three"=>8, "four"=>9, "five"=>10}
Upvotes: 3
Reputation: 12558
Your array has two entries of the same hash object. So if you change the hash object anywhere, it will change in both array entries. To avoid having the same exact hash object in each array entry, you can duplicate the hash before inserting, by changing multiArray << hash
to multiArray << hash.dup
Upvotes: 2