O'Reilly logo

Ruby Cookbook by Leonard Richardson, Lucas Carlson

Stay ahead with the world's most comprehensive technology and business learning platform.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

Start Free Trial

No credit card required

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 ...

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more.

Start Free Trial

No credit card required