0

I have the hash below from which I'm trying to get "value" of the element matching '"year" => "2014"' and '"period" => "M06"'.

result = {"status"=>"REQUEST_SUCCEEDED", "responseTime"=>28, "message"=>[], "Results"=>{"series"=>[{"seriesID"=>"LNU03034342", "data"=>[{"year"=>"2014", "period"=>"M06", "periodName"=>"June", "value"=>"11.1", "footnotes"=>[{}]}, {"year"=>"2014", "period"=>"M05", "periodName"=>"May", "value"=>"16.8", "footnotes"=>[{}]}, {"year"=>"2014", "period"=>"M04", "periodName"=>"April", "value"=>"18.8", "footnotes"=>[{}]}, {"year"=>"2014", "period"=>"M03", "periodName"=>"March", "value"=>"18.7", "footnotes"=>[{}]}, {"year"=>"2014", "period"=>"M02", "periodName"=>"February", "value"=>"17.6", "footnotes"=>[{}]}, {"year"=>"2014", "period"=>"M01", "periodName"=>"January", "value"=>"16.0", "footnotes"=>[{}]}]}]}}

So far I have 'result["Results"]["series"][0]["data"]' which yields:

{"year"=>"2014", "period"=>"M06", "periodName"=>"June", "value"=>"11.1", "footnotes"=>[{}]}
{"year"=>"2014", "period"=>"M05", "periodName"=>"May", "value"=>"16.8", "footnotes"=>[{}]}
{"year"=>"2014", "period"=>"M04", "periodName"=>"April", "value"=>"18.8", "footnotes"=>[{}]}
{"year"=>"2014", "period"=>"M03", "periodName"=>"March", "value"=>"18.7", "footnotes"=>[{}]}
{"year"=>"2014", "period"=>"M02", "periodName"=>"February", "value"=>"17.6", "footnotes"=>[{}]}
{"year"=>"2014", "period"=>"M01", "periodName"=>"January", "value"=>"16.0", "footnotes"=>[{}]}

Now, all the keys in each element of this parent hash are the same, so I'll need to get what I want by searching period for M06, select that element, then get value from the element. How do I do this?

I realize that technically I could take the first of the nested hashes since I'm seeking the highest period, but that seems sloppy.

1 Answer 1

2

You can do as

result["Results"]["series"][0]["data"].find(->(){ {} }) do |hash|
    hash[period] == 'M06'
end.fetch(value, "period not found")

#find - Passes each entry in enum to block. Returns the first for which block is not false. If no object matches, calls ifnone and returns its result when it is specified, or returns nil otherwise.

Thus for any reason if 'M06' value not found for the key period from any of the hash, then the #find will call the argument I passed to it, like ->() { {} }.call, and return the empty hash, otherwise if 'M06' found for the key 'period of any hash,then that hash will be returned. On this returned hash, I am calling Hash#fetch method.

Example to explain this :-

#!/usr/bin/env ruby

array = {a: 1, b: 2}, { a: 4, b: 11}

def fetch_value(array, search_key, search_value, fetch_key)
  array.find(->(){ {} }) do |h|
    h[search_key] == search_value 
  end.fetch(fetch_key, "#{search_value} is not found for #{search_key}.")
end

fetch_value(array, :a, 11, :b) # => "11 is not found for a."
fetch_value(array, :a, 4, :b) # => 11
Sign up to request clarification or add additional context in comments.

2 Comments

I see that this works, thank you. I don't quite follow what ->(){ {} } does, however. Do you mind elaborating?
@UserDuser That is a Proc object, I created it using using staby operator.. this is same as lambda() { {} }.. Is this now clear ? The proc object contains an empty hash ({}), which will be returned, when you call the proc object.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.