简体   繁体   中英

Get set of hashes from array of hashes between two date values

I have an array of hashes that contains a date and total key.

For example:

hash = [{
  "Date"=>"01/01/2016",
  "Total"=>10
},{
  "Date"=>"02/01/2016",
  "Total"=>20
},{
  "Date"=>"03/01/2016",
  "Total"=>30
},{
  "Date"=>"04/01/2016",
  "Total"=>40
},{
  "Date"=>"05/01/2016",
  "Total"=>50
}]

What I want to do is pass two dates to a method that then returns only hashes whose dates are either matching or between the two dates.

So for example:

get_data(startDate, endDate)

end

Where the startDate and endDate are '02/01/206' and 04/01/2016

Would return:

{
  "Date"=>"02/01/2016",
  "Total"=>20
},{
  "Date"=>"03/01/2016",
  "Total"=>30
},{
  "Date"=>"04/01/2016",
  "Total"=>40
}
def get_data(start_date, end_date, hash)
  hash.select{|entry| entry["Date"].to_date.between?(start_date.to_date, end_date.to_date) }
end

I endorse @Steve's answer, but would like to point out you could use Ruby's somewhat obscure flip-flop operator .

Below, arr is the array of hashes in your example.

require 'date'

h = arr.each_with_object({}) { |g,h| h[Date.strptime(g["Date"], '%d/%m/%Y')] = g }
  #=> {#<Date: 2016-01-01 ((2457389j,0s,0n),+0s,2299161j)>=>
  #      {"Date"=>"01/01/2016", "Total"=>10},
  #    #<Date: 2016-01-02 ((2457390j,0s,0n),+0s,2299161j)>=>
  #      {"Date"=>"02/01/2016", "Total"=>20},
  #    #<Date: 2016-01-03 ((2457391j,0s,0n),+0s,2299161j)>=>
  #      {"Date"=>"03/01/2016", "Total"=>30},
  #    #<Date: 2016-01-04 ((2457392j,0s,0n),+0s,2299161j)>=>
  #      {"Date"=>"04/01/2016", "Total"=>40},
  #    #<Date: 2016-01-05 ((2457393j,0s,0n),+0s,2299161j)>=>
  #      {"Date"=>"05/01/2016", "Total"=>50}}  

range =  Date.strptime('02/01/2016', '%d/%m/%Y')..Date.strptime('04/01/2016', '%d/%m/%Y')
  #=> #<Date: 2016-01-02 ((2457390j,0s,0n),+0s,2299161j)>..
  #   #<Date: 2016-01-04 ((2457392j,0s,0n),+0s,2299161j)> 

The flip-flop operator is used to determine the keys that fall within the given range:

keeper_keys = h.keys.sort.select { |d| range.include?(d) .. true ? true : false }
  #=> [#<Date: 2016-01-02 ((2457390j,0s,0n),+0s,2299161j)>,
  #    #<Date: 2016-01-03 ((2457391j,0s,0n),+0s,2299161j)>,
  #    #<Date: 2016-01-04 ((2457392j,0s,0n),+0s,2299161j)>]

h.select { |k,_| keeper_keys.include?(k) }.values
  #=> [{"Date"=>"02/01/2016", "Total"=>20},
  #    {"Date"=>"03/01/2016", "Total"=>30},
  #    {"Date"=>"04/01/2016", "Total"=>40}] 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM