Cover by Leonard Richardson, Lucas Carlson

Safari, the world’s most comprehensive technology and business learning platform.

Find the exact information you need to solve a problem on the fly, or go deeper to master the technologies and skills you need to succeed

Start Free Trial

No credit card required

O'Reilly logo

5.5. Using an Array or Other Modifiable Object as a Hash Key

Problem

You want to use a modifiable built-in object (an array or a hash, but not a string) as a key in a hash, even while you modify the object in place. A naive solution tends to lose hash values once the keys are modified:

	coordinates = [10, 5]
	treasure_map = { coordinates => 'jewels' }
	treasure_map[coordinates]                    # => "jewels"

	# Add a z-coordinate to indicate how deep the treasure is buried.
	coordinates << -5

	coordinates                                  # => [10, 5, -5]
	treasure_map[coordinates]                    # => nil
	                                             # Oh no!

Solution

The easiest solution is to call the Hash#rehash method every time you modify one of the hash's keys. Hash#rehash will repair the broken treasure map defined above:

	treasure_map.rehash
	treasure_map[coordinates]                    # => "jewels"

If this is too much code, you might consider changing the definition of the object you use as a hash key, so that modifications don't affect the way the hash treats it.

Suppose you want a reliably hashable Array class. If you want this behavior universally, you can reopen the Array class and redefine hash to give you the new behavior. But it's safer to define a subclass of Array that implements a reliable-hashing mixin, and to use that subclass only for the Arrays you want to use as hash keys:

	module ReliablyHashable
	 def hash
	    return object_id
	  end
	end

	class ReliablyHashableArray < Array
	  include ReliablyHashable
	end

It's now possible to keep track of the jewels:

 coordinates = ReliablyHashableArray.new([10,5]) treasure_map ...

Find the exact information you need to solve a problem on the fly, or go deeper to master the technologies and skills you need to succeed

Start Free Trial

No credit card required