2014-02-02 4 views
0

У меня есть массив массивов, я хочу выбрать массивы с датой, которая попадает в определенный диапазон.Выбор массивов между диапазонами дат с Ruby

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"]] 

Например, я хотел бы получить все массивы между 2014-01-24 и 2014-01-29.

+0

Если какой-либо из ответов были в использовании, рассмотреть вопрос о выборе тот, который наиболее полезным для вас. –

ответ

2
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"]] 
4

Без использования 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"]] 

или

ar.select { |_,d| ("2014-01-24".."2014-01-29").cover?(d) } 

Примечание это зависит от даты выражается в год-месяц-день заказа.

Редактировать: Раньше я использовал то, что считал Range#include?, но @ toro2k указал, что это фактически Enumerable#include?, что довольно медленно. Я подумал, что Range#include? сможет просто сравнивать конечные точки, так как для строк используется <=>. Не так; он применяется только тогда, когда значения являются числовыми или одиночными символьными строками (иначе это super с до Enumerable#include?). Это меня озадачило. Для всех, кого это интересует, я думаю, теперь я понимаю причину ограниченного применения.

Мы хотели бы ('aa'..'zz').include?('mno') вести себя так же, как

('aa'..'zz').to_a.include?('mno') => false 

Предположим, что мы делаем это:

class String 
    alias :spaceship :<=> 
    def <=>(other) 
    spaceship(other.size > 1 ? other[0,2] : other) 
    end 
end 

Тогда

"mno" >= 'aa' # => true 
"mno" <= 'zz' # => true 

так что если Range#include? рассматриваются только конечные точки,

('aa'..'zz').include?("mno") # => true 
+1

Одна из приятных вещей, связанных с датами ISO 8601, заключается в том, что они сравниваются разумно, как строки. –

+0

@muistooshort это ново для меня спасибо за подсказку, любая ссылка на это ?? – bjhaid

+1

@bjhaid, я думаю, что μ означает, что поскольку даты [ISO 8601] (http://en.wikipedia.org/wiki/ISO_8601) являются yyyy-mm-dd, две даты, выраженные в виде строк, можно упорядочить с помощью ' <=> '; т. е. сравниваются yyyy, если оба они одинаковы, сравниваются миллиметры, если они сравниваются с dd. –

2

Я хотел бы использовать 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"]] 
Смежные вопросы