I am trying to initialize a Hash of Arrays such as
@my_hash = Hash.new(Array.new) so that I can:
@my_hash["hello"].push("in the street") => ["in the street"] @my_hash["hello"].push("at home") => ["in the street", "at home"] @my_hash["hello"] =>["in the street", "at home"] The problem is that any new hash key also return ["in the street", "at home"]
@my_hash["bye"] => ["in the street", "at home"] @my_hash["xxx"] => ["in the street", "at home"] !!!???
What am I doing wrong what would be the correct way to initialize a Hash of Arrays?
@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 new is 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 cause some_key to be inserted in the hash.
Try this:
@my_hash = Hash.new { |h, k| h[k] = Array.new }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With