Change the default hash value

Ruby allows you to define default values ​​for hashes:

h=Hash.new(['alright']) h['meh'] # => ["alright"] 

When a hash is displayed, a value assignment appears, but the changed default value is not executed. Where is the 'bad' ?

 h['good']=['fine','dandy'] h['bad'].push('unhappy') h # => {"good"=>["fine", "dandy"]} 

'bad' appears if we explicitly ask a question.

 h['bad'] # => ["alright", "unhappy"] 

Why is the changed default not displayed when the hash is displayed?

+8
ruby hash invisible
source share
2 answers

The default value for the hash does not work as you expect. When you say h[k] , the process will look like this:

  • If we have key k , return its value.
  • If we have a default value for Hash, return that default value.
  • If we have a block to provide default values, execute the block and return its return value.

Note that (2) and (3) say nothing about inserting k into the hash. By default, the default turns h[k] into this:

 h.has_key?(k) ? h[k] : the_default_value 

Thus, simply accessing a non-existent key and getting the default value back will not add the missing key to the hash.

In addition, anything:

 Hash.new([ ... ]) # or Hash.new({ ... }) 

it is almost always a mistake, because for all default values ​​you will use exactly the same default array or Hash. For example, if you do this:

 h = Hash.new(['a']) h[:k].push('b') 

Then h[:i] , h[:j] , ... all will return ['a', 'b'] and this is rarely what you want.

I think you are looking for the default block form :

 h = Hash.new { |h, k| h[k] = [ 'alright' ] } 

This will do two things:

  • Access to a nonexistent key will add this key to the Hash, and it will have the provided array as its value.
  • All default values ​​will be different objects, so changing them will not change the rest.
+11
source share

It so happened that you changed the default value for the hash, push ing 'unhappy' to h['bad'] . What you did not actually added “badly” to the hash, so it does not appear when you check h .

After you provided the code, I tried this:

 >> ph['bleh'] => ["allright", "unhappy"] 

Which, of course, tells me that the default value has been changed. In response to your question, “Why does the changed default not appear when the hash is displayed?”, You will need to add an element to it, and not just get it:

 >> h['bleh'] # Doesn't add 'bleh' to the hash >> ph => {"good"=>["fine", "dandy"]} # See, no extra values >> h['bleh'] = h.default # Does add a new key with the default value >> ph => {"good"=>["fine", "dandy"], "bleh"=>["allright", "unhappy"]} 
+2
source share

All Articles