I will just paste down a simple example i tried so that it would be clear to those who read 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, its possible to identify the map between the key and the value.
Could some one please explain me this behaviour of ruby hash and what are the properties of hash keys.
1) As i mentioned above, the object_id hasn't changed - then why is the value set to nil.
2) Is there any possible way so that i can get back the value '12' from the hash 'h' because h[[1,2,3,4]] as mentioned above returns nil.
This happens because the key should not have its value changed while it is in use. If the value changes, we should rebuild the hash, based on its current value. Look at Ruby API for rehash
method. You can get back the value, by rebuilding the hash again after the key is changed, like this:
irb(main):022:0> h.rehash
=> {[1, 2, 3, 4]=>12}
irb(main):023:0> h[a]
=> 12
Hash keys are checked using the #eql?
method, and since [1, 2, 3]
isn't .eql?
to [1, 2, 3,4]
your hash lookup has a different result.
Maybe you want to be using something other than an Array
as your Hash
key if the semantics aren't working for you?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With