Shorthand method for accessing values in a Hash


Today we will look into a interesting problem in ruby. 'Accessing the hash values through the key'. When the hash is not nested, we can easily access the elements through keys. Let's take a simple hash example,

simple_hash = {
 	"key1" => "value1",
 	"key2" => "value2"
}

If i need the "value1" from the hash, i can access it by simply writing simple_hash["key1"]. Similarly for "value2".

But what if hash is nested. Take the following example,

nested_hash = {
  "key1" => "value1",
  "key2" => "value2",
  "key3" => {
		"child_key1" => "child_value1",
		"child_key2" => "child_value2",
		"child_key3" => {
			"code" => "brahma"
		}
	},
  "key4" => {
    "child_key1" => "child_value1_in_key4",
    "child_key2" => "child_value2_in_key4",
    "child_key3" => {
      "code" => "duplicate_keys"
    }
  }
}

# nested_hash["key3"]["child_key2"] returns "child_value2"
# nested_hash["key3"]["child_key3"]["code"] returns "brahma"
# nested_hash["key5"]["child_key1"] raises  raises "NoMethodError"

In the first two cases, I can access the values by passing the keys. If the hash is 10 times nested, then i have pass 10 keys to access the most nested value. The code will look ugly. If the hash is more nested, then accessing the value from the hash is very difficult.

In the last case, we got an exception, since 'key5' doesn't exist in the hash.

Why can't we come up with the new solution that overcomes this syntax and rescues the exception? Let's implement a method which solves this problem. Here is the recursive solution.


def get_value(hash, keyword, options={})
  hash = get_value(hash, options[:parent]) if options[:parent]
  if (hash.respond_to?(:keys) && hash.keys.include?(keyword))
      hash[keyword]
  elsif hash.respond_to?(:find)
    result = nil
    hash.values.find { |value| result = get_value(value, keyword) }
    result
  end
end

# puts get_value(nested_hash, "child_key2") => "child_value2"
# puts get_value(nested_hash, "code") => "brahma"
# puts get_value(nested_hash, "key5") => nil
# puts get_value(nested_hash, "child_key2", { :parent => "key4" }) => "child_value2_in_key4"
# puts get_value(nested_hash, "child_key2", { :parent => "key3" }) => "child_value2"
← Return to Home
***