qrrr qrrr - 6 months ago 7
Ruby Question

How do I add a key/value pair to the beginning of a hash?

My code is:

hash = { two: 2, three: 3 }

def hash_add(hash, new_key, new_value)
temp_hash = {}

temp_hash[new_key.to_sym] = new_value
temp_hash.merge!(hash)
hash = temp_hash
puts hash

end

hash_add(hash, 'one', 1)


Within the method,
puts hash
returns
{ :one => 1, :two => 2, :three => 3 }
, but when
hash1
is put to the method, it remains unchanged afterward. It's like the assignment isn't carrying itself outside of the function.

I guess I could return the updated hash and set the hash I want to change to it outside the method:

hash = hash_add(hash, 'one', 1)


But I just don't see why the assignment I give to the hash does not stick outside of the method.

I have this, which works:

def hash_add(hash, new_key, new_value)
temp_hash = {}

temp_hash[new_key.to_sym] = new_value
temp_hash.merge!(hash)
hash.clear

temp_hash.each do |key, value|
hash[key] = value
end
end


Which gives me what I'm wanting when this method is called, but it just seems a little excessive to have to rebuild the hash like that.

G_A G_A
Answer

Ruby passes objects to methods by value, but the value is the reference to the object, so when you set hash=temp_hash within the add_hash method, that change only applies inside the method. The value of hash outside the method is unchanged.

def hash_add(hash, new_key, new_value)
  temp_hash = {}

  temp_hash[new_key.to_sym] = new_value
  temp_hash.merge!(hash)
  hash = temp_hash
  hash
end
h2 = hash_add(hash, 'one', 1)
hash
=> {:two=>2, :three=>3}
h2
=>{:one=>1, :two=>2, :three=>3}

If you want hash to be updated, you need to replace the contents of hash rather than re-point hash at a new object as you did with the clear and re-adding the values. You can also do it with the replace method.

def hash_add(hash, new_key, new_value)
  temp_hash = {}

  temp_hash[new_key.to_sym] = new_value
  temp_hash.merge!(hash)
  hash.replace temp_hash
end

There are some good diagrams about pass by value in "Is Ruby pass by reference or by value?"

Comments