Cory O'Daniel – These are just words Software development, thoughts, and randomness

30Dec/092

Ruby – Getting deeply nested values from a hash in one line of code

I occasionally have deeply nested values in a hash that I need to get to, for example:

1
2
3
4
5
6
7
8
@event = {
  #... *SNIP* ...
  :coordinator => {
    :api_license => {
      :key => "SECRET COOL KEY"
    }
  }
}

What really sucks is to do things like:

1
2
3
if @event[:coordinator] && @event[:coordinator][:api_license]
  @key_i_need = @event[:coordinator][:api_license][:key]
end

What's the fix? A seek method for a hash, throw this in your core extensions files/folders or where ever.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Hash
  def seek(*_keys_)
    last_level    = self
    sought_value  = nil
 
    _keys_.each_with_index do |_key_, _idx_|
      if last_level.is_a?(Hash) && last_level.has_key?(_key_)
        if _idx_ + 1 == _keys_.length
          sought_value = last_level[_key_]
        else                   
          last_level = last_level[_key_]
        end
      else 
        break
      end
    end
 
    sought_value
  end 
end

Now you can do this:

1
@key_i_need = @event.seek :coordinator, :api_license, :key

If there is any subhash that doesn't exist on the way to the value or if the value itself doesn't exist, nil is returned.

This is really great if you are passing around a lot of JSON data between applications and need to get to one specific value and you don't want to ugly up your code.

Post to Twitter Post to Digg Post to Facebook Post to Reddit Post to StumbleUpon

Comments (2) Trackbacks (1)
  1. How it will be for a json output like this…

    {
    “query”: {
    “results”: {
    “industry”: [
    {
    "id": "112",
    "name": "Agricultural Chemicals",
    "company": [
    {
    "name": "Adarsh Plant",
    "symbol": "ADARSHPL"
    },
    {
    "name": "Agrium Inc",
    "symbol": "AGU.DE"
    }
    },
    ]
    {
    “id”: “914″,
    “name”: “Water Utilities”,
    “company”: [
    {
    "name": "Acque Potabili",
    "symbol": "ACP.MI"
    },
    {
    "name": "Water Resources Group",
    "symbol": "WRG.AX"
    }
    ]
    }
    ]
    }
    }
    }


Leave a comment