0

I'm looking to have a date range from 1.month.ago..Date.today, then for each day select the maximum temperature (so should get 30 individual numbers), then sum up the results.

I obtain the data in JSON format which is structured like this

{"status": "ok", "data": [{"temperature": 22.4, "date": "20160815-0345"}} 

I parse the data through a loop.

@data['data'].each do |d| maxTotal << [DateTime.parse(d['date']), d['temperature']] end 

But fall short on how to select the maximum for each day and then sum it up.

@total = maxTotal { |a| a[0].to_date == (1.month.ago.to_date) }.max { |a,b| a[1] <=> b[1] }.sum[1] 

    1 Answer 1

    2

    Updated: Tested and Working

    json_data = @data['data'] sum_of_max_temperature_in_each_day = json_data. group_by{ |h| Date.parse(h[:date]) }. reject{ |k, v| !( ((30.days.ago.to_date)..(Date.today)) === k ) }. inject(0){ |sum, h| sum + h.second.max_by{ |h| h[:temperature] }[:temperature] } 

    Explanation (Breaking it down)

    # Example; let json_data be json_data = [ {"temperature": 22.4, "date": "20160815-0345"}, {"temperature": 10.4, "date": "20160815-1435"}, {"temperature": 15.8, "date": "20990101-0430"}, {"temperature": 4, "date": "20160816-0101"} ] # sum of max temperature each day within last 30 days puts json_data. group_by{ |h| Date.parse(h[:date]) }. reject{ |k, v| !( ((30.days.ago.to_date)..(Date.today)) === k ) }. inject(0){ |sum, h| sum + h.second.max_by{ |h| h[:temperature] }[:temperature] } => 26.4 # 1) Group by day puts json_data. group_by{|h| Date.parse( h[:date] )} { Mon, 15 Aug 2016=>[ {:temperature=>22.4, :date=>"20160815-0345"}, {:temperature=>10.4, :date=>"20160815-1435"} ], Thu, 01 Jan 2099=>[ {:temperature=>15.8, :date=>"20990101-0430"} ], Tue, 16 Aug 2016=>[ {:temperature=>4, :date=>"20160816-0101"} ] } # 2) Remove those not within the last 30 days puts json_data. group_by{ |h| Date.parse(h[:date]) }. reject{ |k, v| !( ((30.days.ago.to_date)..(Date.today)) === k ) } { Mon, 15 Aug 2016=>[ {:temperature=>22.4, :date=>"20160815-0345"}, {:temperature=>10.4, :date=>"20160815-1435"} ], Tue, 16 Aug 2016=>[ {:temperature=>4, :date=>"20160816-0101"} ] } # 3) Showing what's happening inside the inject() block. puts json_data. group_by{ |h| Date.parse(h[:date]) }. reject{ |k, v| !( ((30.days.ago.to_date)..(Date.today)) === k ) }. inject(0){ |sum, h| puts "h ==> #{h}"; puts "h.second ==> #{h.second}"; puts "h.second.max_by ==> #{h.second.max_by{ |h| h[:temperature] }[:temperature]}" } h ==> [ Mon, 15 Aug 2016, [ {:temperature=>22.4, :date=>"20160815-0345"}, {:temperature=>10.4, :date=>"20160815-1435"} ] ] h.second ==> [ {:temperature=>22.4, :date=>"20160815-0345"}, {:temperature=>10.4, :date=>"20160815-1435"} ] h.second.max_by ==> 22.4 h ==> [ Tue, 16 Aug 2016, [ {:temperature=>4, :date=>"20160816-0101"} ] ] h.second ==> [ {:temperature=>4, :date=>"20160816-0101"} ] h.second.max_by ==> 4 
    4
    • Thanks Jay, Could you explain the use of second in h.second.max_by? It seem that this is grating the second record of the day, not the max.CommentedSep 1, 2016 at 3:08
    • @DollarChills ohh no, the .second refers to the second of variable h in which h is an Array with a size of two as you could see from above. You will notice that h.first is the Key, and h.second is corresponding Value. This is because inject() loops through each key-value pair in the hash (refer to part 2) hash above), and then h becomes something like [key, value] Array instead of a hash {key: value}. That is why again the h.second refers to the value pointed by the key (key is a Date, and value is an Array of hashes of :temperature and :date; see above) Hope this helpsCommentedSep 1, 2016 at 8:34
    • Thanks for the explanation. Seems to work just fine. Thanks very much for your help!CommentedSep 1, 2016 at 23:48
    • @DollarChills no worries. Glad to be of help :)CommentedSep 2, 2016 at 9:16

    Start asking to get answers

    Find the answer to your question by asking.

    Ask question

    Explore related questions

    See similar questions with these tags.