Hash.new
Ruby Hashes can do some pretty cool things, depending how you create them.
>> h = Hash.new
=> {}
>> h[:foo]
=> nil
>> h.keys
=> []
Ok, nothing crazy there. Hash.new
can take a value, which will become the default value returned if a key isn't found in the hash.
>> h = Hash.new('bacon')
=> {}
>> h[:foo]
=> "bacon"
>> h.keys
=> []
Alright, pretty cool. Not quite sure why you might want to do that, but I guess it's a good way to avoid the dreaded nil
. We can use this construct to create a cheap counter.
>> h = Hash.new(0)
=> {}
>> h[:foo]
=> 0
>> h[:foo] += 1
=> 1
>> h.keys
=> [:foo]
>> h[:foo] += 1
=> 2
>> h[:foo] += 1
=> 3
>> h[:foo]
=> 3
Pretty cool. What next? How about a block? The arguments (?) to the block represent the hash itself (h
) and the key being accessed (k
). We can use this to create a hash that will automatically populate itself with the value of the key being called.
>> h = Hash.new { |h,k| h[k] = k }
=> {}
>> h['foo']
=> "foo"
>> h.keys
=> ["foo"]
>> h['foo']
=> "foo"
>> h.keys
=> ["foo"]
Ok, not very useful, but what if we set the value of the key to fetch the key as an HTTP request?
>> require 'httparty'
=> true
>> h = Hash.new { |h,k| h[k] = HTTParty.get(k).body }
=> {}
>> h['http://rodreegez.com']
=> # takes a while, but returns the HTML of my personal site
>> h['http://rodreegez.com']
=> # returns instantly the same HTML
Boom. The cheapest caching construct available to man. Maybe. I urge you to try that last one. It's probably useless but kinda fun.
I hope you keep this in mind next time you are using a hash. It can come in handy!
I pinched most of the above from here: http://endofline.wordpress.com/2010/12/24/hash-tricks/