Henry Cipolla

Tech, gaming, motorsports, and whatever else

Creating an Array of Hashes in Ruby

I just made a simple mistake which I figure would be good share with anybody new-ish to Ruby. I wrote the following code to create an array of hashes and fill in some values. Can you guess what the output is?


#!/usr/bin/env ruby

testArray = Array.new(5, Hash.new)
0.upto(4) do |i|
testArray[i][:value] = i
end

0.upto(4) do |i|
puts testArray[i][:value]
end

If you said:
4
4
4
4
4

then you are right. The problem with this code is the Hash.new only creates one hash. And then each element in the array is a reference to that hash. So when any value is changed, all are changed. Instead, moving the hash creation inside the loop fixes everything:

#!/usr/bin/env ruby

testArray = Array.new(5, 0)
0.upto(4) do |i|
testArray[i] = Hash.new
testArray[i][:value] = i
end

0.upto(4) do |i|
puts testArray[i][:value]
end

outputs:
0
1
2
3
4

There Are 6 Responses So Far. »

  1. I am new to Ruby so I spent 4 hours trying to figure this out. I found your post and had everything working in 5 minutes. Thank you!

  2. I kind of prefer the loops this way:

    (0..4).each do { |i|
    puts testArray[i][:value]
    }

    …they are just easier to read.

    The bit about having to initialize every hash in the array was also nice for this noob to learn.

  3. Thanks for the fix. Was wondering why my array values kept getting overwritten.

  4. thanks a lot

  5. I would just do:

    ===========
    testArray = Array.new
    (0..4).each do |i|
    testArray < i }
    end
    (0..4).each do |i|
    puts testArray[i][:value]
    end

    You could also inspect your data structure to make sure you created what you wanted:
    puts testArray.inspect
    ===========

  6. Thanks! I was about to lose my mind until I saw this article.

Post a Response