@my_hash = Hash.new(Array.new)
This creates exactly one array object, which is returned every time a key is not found. Since you only ever mutate that array and never create a new one, all your keys map to the same array.
What you want to do is:
@my_hash = Hash.new {|h,k| h[k] = Array.new }
or simply
@my_hash = Hash.new {|h,k| h[k] = [] }
Passing a block to Hash.new differs from simply passing an argument in 2 ways:
-
The block is executed every time a key is not found. Thus you’ll get a new array each time. In the version with an argument, that argument is evaluated once (before
newis called) and the result of that is returned every time. -
By doing
h[k] =you actually insert the key into the hash. If you don’t do this just accessing@my_hash[some_key]won’t actually causesome_keyto be inserted in the hash.