I have an array of arrays, I want to select arrays with a date that falls in a certain range.
ar = [[72162, \"2014-01-21\"],
[53172, \"2014-01-22\"],
[4937
I'd use Comparable#between?
ar = [ [72162, "2014-01-21"],
[53172, "2014-01-22"],
[49374, "2014-01-23"],
[41778, "2014-01-24"],
[34182, "2014-01-25"],
[58869, "2014-01-26"],
[72162, "2014-01-27"],
[43677, "2014-01-28"],
[37980, "2014-01-29"],
[87354, "2014-01-30"],
[43677, "2014-01-31"]
]
ar.select { |_,e| e.between?("2014-01-24","2014-01-29") }
# => [[41778, "2014-01-24"],
# [34182, "2014-01-25"],
# [58869, "2014-01-26"],
# [72162, "2014-01-27"],
# [43677, "2014-01-28"],
# [37980, "2014-01-29"]]
require 'date'
range = Date.parse("2014-01-24")..Date.parse("2014-01-29")
ar.select { |x| range.include?(Date.parse(x[1])) }
=> [[41778, "2014-01-24"],
[34182, "2014-01-25"],
[58869, "2014-01-26"],
[72162, "2014-01-27"],
[43677, "2014-01-28"],
[37980, "2014-01-29"]]
Without using Date
:
ar.select { |_,d| d >= "2014-01-24" && d <= "2014-01-29" }
=> [[41778, "2014-01-24"],
[34182, "2014-01-25"],
[58869, "2014-01-26"],
[72162, "2014-01-27"],
[43677, "2014-01-28"],
[37980, "2014-01-29"]]
or
ar.select { |_,d| ("2014-01-24".."2014-01-29").cover?(d) }
Note this depends on the date being expressed in year-month-day order.
Edit: I formerly used what I thought was Range#include?, but @toro2k pointed out that is was actually Enumerable#include?, which is quite slow. I had thought that Range#include?
would be able to just compare endpoints, since <=>
is defined for Strings. Not so; it only applies when the values are numeric or single character strings (else it super
s to Enumerable#include?
). That puzzled me. For anyone interested, I think I now understand the reason for the restricted application.
We would want ('aa'..'zz').include?('mno')
to behave the same as
('aa'..'zz').to_a.include?('mno') => false
Suppose we do this:
class String
alias :spaceship :<=>
def <=>(other)
spaceship(other.size > 1 ? other[0,2] : other)
end
end
Then
"mno" >= 'aa' # => true
"mno" <= 'zz' # => true
so if Range#include?
only considered the endpoints,
('aa'..'zz').include?("mno") # => true