Ruby: hash key properties

I will just insert a simple example that I tried so that it is clear who reads this.

irb(main):001:0> h = { } => {} irb(main):002:0> a=[1,2,3] => [1, 2, 3] irb(main):003:0> a.object_id => 69922343540500 irb(main):004:0> h[a] = 12 #Hash with the array as a key => 12 irb(main):005:0> a << 4 #Modified the array => [1, 2, 3, 4] irb(main):006:0> a.object_id #Object id obviously remains the same. => 69922343540500 irb(main):007:0> h[a] #Hash with the same object_id now returns nil. => nil irb(main):008:0> h #Modified hash => {[1, 2, 3, 4]=>12} irb(main):009:0> h[[1,2,3,4]] #Tried to access the value with the modified key - => nil irb(main):011:0> h.each { |key,value| puts "#{key.inspect} maps #{value}" } [1, 2, 3, 4] maps 12 => {[1, 2, 3, 4]=>12} 

Now when I iterate over the hash, I can identify the map between the key and the value.

Can someone please explain to me this ruby ​​hash behavior and what are the properties of the hash keys.

1) As mentioned above, object_id has not changed - then why is the value set to nil.

2) Is there any possible way that I can return the value '12' from the hash of 'h', because h [[1,2,3,4]], as mentioned above, returns nil.

+4
source share
4 answers

#eql? hash #eql? checked using the #eql? method #eql? , and since [1, 2, 3] not .eql? - [1, 2, 3,4] , your hash search has a different result.

Maybe you want to use something other than Array as your Hash if the semantics don't work for you?

+1
source

This is because the key must not change its value during use. If the value changes, we must rebuild the hash based on its current value. Check out the Ruby API for the rehash method. You can return the value by restoring the hash again after changing the key, for example:

 irb(main):022:0> h.rehash => {[1, 2, 3, 4]=>12} irb(main):023:0> h[a] => 12 
+8
source

ruby hash api gives the answer: the key should not be changed while it is used as a key.

I assume that the hash interval is computed for a and used for a quick search (because the key should not change, the hash is always the same). Therefore, when you do h[a] , it does not find a match ([1,2,3] .hash! = [1,2,3,4] .hash), and when you do h[[1,2,3]] , hashed, and the object does not match ([1,2,3]! = [1,2,3,4]).

The fix is ​​to use object_id as a key because it does not change, h[a.object_id] = 12 will return 12 when the changes are changed. Of course, this has the disadvantage that h[[1,2,3].object_id] will not return 12.

+1
source

Stefan Coleman's answer is more thorough, but a few comments:

Ruby uses the Object # hash method for hash objects.

You can get 12 back, for example, by doing a.delete(4); h[a] a.delete(4); h[a] at this point, [1,2,3] can also be used again as a key.

+1
source

All Articles