Ruby Hash is a destructive and non-destructive method

Couldn't find a previous post that answers my question ... I'm looking into using destructive and non-destructive methods in Ruby. I found an answer to an exercise I'm working on (destructive addition of a number to hash values), but I want to be clear about why some of my earlier solutions didn't work. Here's an answer that works:

  def modify_a_hash(the_hash, number_to_add_to_each_value)
    the_hash.each { |k, v| the_hash[k] = v + number_to_add_to_each_value}


These two solutions come back as non-destructive (since they all use "each", I can't figure out why. To do something destructive, is the equal sign above that does the trick?):

  def modify_a_hash(the_hash, number_to_add_to_each_value)
    the_hash.each_value { |v| v + number_to_add_to_each_value}

  def modify_a_hash(the_hash, number_to_add_to_each_value)
    the_hash.each { |k, v| v + number_to_add_to_each_value}



source to share

2 answers

The terms "destructive" and "non-destructive" are a little misleading here. Better to use standard terminology "in place" and "returns a copy".

Usually, methods that change place are appended !

to the name to serve as a warning, for example gsub!

String. Some methods prior to this convention do not have them, for example push



performs the task in a loop. Your other examples are not really helpful as it each

returns the original object that is iterated over regardless of the results.

If you want to return a copy, you must do this:

def modify_a_hash(the_hash, number_to_add)
    the_hash.collect do |k, v|
      [ k, v + number_to_add ]


This will return a copy. The inner operation collect

converts the key-value pairs to new key-value pairs with the setting applied. No =

, as there is no destination.

The external method will Hash[]

convert these key-value pairs to the correct Hash object. Then it comes back and is independent of the original.

Typically, a non-destructive or "copy-back" method is to create a new independent version of what it is manipulating in order to store the results. This applies to String, Array, Hash, or any other class or container you can work with.



Perhaps this slightly different example will be helpful.

We have a hash:

2.0.0-p481 :014 > hash
 => {1=>"ann", 2=>"mary", 3=>"silvia"}


Then we iterate over it and change all letters to uppercase:

2.0.0-p481 :015 > hash.each { |key, value| value.upcase! }
 => {1=>"ANN", 2=>"MARY", 3=>"SILVIA"}


The original hash changed because we were using upcase! Method.

Compare with the method without! a sign that doesn't change the hash value:

2.0.0-p481 :017 > hash.each { |key, value| value.downcase }
=> {1=>"ANN", 2=>"MARY", 3=>"SILVIA"}




All Articles