Select arrays between date ranges with Ruby

前端 未结 3 1439
一个人的身影
一个人的身影 2020-12-06 09:09

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         


        
相关标签:
3条回答
  • 2020-12-06 09:18

    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"]]
    
    0 讨论(0)
  • 2020-12-06 09:23
    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"]]
    
    0 讨论(0)
  • 2020-12-06 09:25

    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 supers 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
    
    0 讨论(0)
提交回复
热议问题