开发者

How can I initialize an Array inside a Hash in Ruby [duplicate]

This question already has answers here: Strange, unexpected behavior (disappearing/changing values开发者_StackOverflow社区) when using Hash default value, e.g. Hash.new([]) (4 answers) Closed 1 year ago.

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:

  1. 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.

  2. 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 }


The argument for Hash.new is for the default value for new hash keys, so when you pass it a reference that reference will be used for new hash keys. You're updating that reference when you call...

hash["key"].push "value"

You need to pass a new reference into the hash key before pushing values to it...

hash["key1"] = Array.new
hash["key1"].push "value1"
hash["key2"] = Array.new
hash["key2"].push "value2

You could try encapsulating this into a helper method as well.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜