【问题标题】:Sorting array elements by date按日期对数组元素进行排序
【发布时间】:2014-10-19 02:39:33
【问题描述】:

我有以下数组。

dates = ["6/23/2014", "8/5/2014", "8/19/2014", "6/26/2014", "8/19/2014", "8/19/2014",
"7/8/2014", "6/3/2014", "7/30/2014", "7/3/2014", "6/3/2014", "6/26/2014"]

我们的数组存储了 10 个字符串对象。为了按照我的方式对它们进行排序,我需要重新排列每个元素。

"2014/8/5", "2014/8/19", "2014/8/19", etc.

这样,例如,2014 年 1 月 1 日不会早于 1994 年 12 月 13 日。

我尝试了以下

dates.sort_by {|date|date.split(/[\/]/).rotate(-1).join('/')}

我想按日期对这个数组进行排序,最新的日期在前。

实际输出

8/5/2014
8/19/2014
8/19/2014
8/19/2014
7/8/2014
7/30/2014
7/3/2014
6/3/2014
6/3/2014
6/26/2014

预期输出

8/19/2014
8/19/2014
8/19/2014
8/5/2014
7/30/2014
7/3/2014
6/26/2014
6/3/2014
6/3/2014

解决方案涉及使用 Ruby 数组类 sort_by 方法。我想使用日期格式进行排序,其中较新的日期排在较早的日期之前。

我的问题是,如何根据日期对数组进行排序。

如果这是一个愚蠢的问题,我深表歉意,但我已经搜索了这个网站,但找不到任何结果。

提前感谢您的帮助。

【问题讨论】:

    标签: ruby arrays sorting date


    【解决方案1】:

    试试:

    dates.sort_by { |s| Date.strptime(s, '%m/%d/%Y') }
    

    如果您希望从最新日期开始:

    dates.sort_by { |s| Date.strptime(s, '%m/%d/%Y') }.reverse
    

    【讨论】:

      【解决方案2】:

      我不知道为什么您的预期输出仅包含 12 个条目中的 9 个,并且您提到了一个大小为 10 的数组,但我相信您想要对所有 12 个进行排序。我的偏好是按照 @ BroiSatse 有,但我将提供两种不使用 Date 类的方法的方法。我将它们包括在内是因为它对于那些刚接触 Ruby 的人来说有一些有趣的方面。

      dates = [
        "6/23/2014", "8/5/2014", "8/19/2014", "6/26/2014", "8/19/2014", "10/19/2014",
        "7/8/2014", "6/3/2014", "7/30/2014", "7/3/2014", "6/3/2014", "6/26/2014"
      ]
      

      我稍微更改了dates,使其包含具有两位数月份的日期 ("10/19/2014")。

      按整数数组排序

      dates.sort_by { |d| d.split(?/).rotate(-1).map { |e| -e.to_i } }
        #=> ["10/19/2014", "8/19/2014", "8/19/2014", "8/5/2014", "7/30/2014", "7/8/2014",
        #    "7/3/2014", "6/26/2014", "6/26/2014", "6/23/2014", "6/3/2014", "6/3/2014"]
      

      这就是正在发生的事情。

      enum = dates.sort_by
        #=> #<Enumerator: [
        #     "6/23/2014", "8/5/2014", "8/19/2014", "6/26/2014", "8/19/2014", "10/19/2014",
        #     "7/8/2014", "6/3/2014", "7/30/2014", "7/3/2014", "6/3/2014", "6/26/2014"
        #   ]:sort_by>
      

      如您所见,enum 是一个枚举器。它传递给其块的第一个值是"6/23/2014",它分配给块变量:

      d = "6/23/2014"
      
      a = d.split(?/)
        #=> ["6", "23", "2014"]
      b = a.rotate(-1)
        #=> ["2014", "6", "23"]
      c = b.map { |e| -e.to_i }
        #=> [-2014, -6, -23]
      

      同样,enum 的第三个元素转换为:

      "8/19/2014".split(?/).rotate(-1).map { |e| -e.to_i }
        #=> [-2014, -8, -19]
      

      sort_by 使用Array#<=> 来比较元素对。阅读该文档后,您将了解原因:

      [-2014, -6, -23] <=> [-2014, -8, -19]
        #=> 1
      

      意味着"8/19/2014" 在排序中应该在"6/23/2014" 之前。

      顺便说一句,有必要将月份和日期从字符串转换为整数,因为这些字符串不包含用于单个数字值的前导零。如果我们将它们保留为字符串,"8" &gt; "15",这不是我们想要的。由于无论如何我们都在转换为整数,因此将它们设为负数比将它们设为正数并将reverse 应用于已排序的数组更容易。

      按年-月-日顺序排序,必要时用前导零填充,然后反转

      dates.sort_by do |d|
        d.sub(/(\d+)\/(\d+)\/(\d+)/) { "%4d%02d%02d" % [$3, $1, $2].map(&:to_i) }
      end.reverse
        #=> ["10/19/2014", "8/19/2014", "8/19/2014", "8/5/2014", "7/30/2014", "7/8/2014",
        #    "7/3/2014", "6/26/2014", "6/26/2014", "6/23/2014", "6/3/2014", "6/3/2014"]
      

      注意

      arr = dates.map do |d|
        d.sub(/(\d+)\/(\d+)\/(\d+)/) { "%4d%02d%02d" % [$3, $1, $2].map(&:to_i) }
      end
        #=> ["20140623", "20140805", "20140819", "20140626", "20140819", "20141019",
        #    "20140708", "20140603", "20140730", "20140703", "20140603", "20140626"]
      
      arr.sort
        #=> ["20140603", "20140603", "20140623", "20140626", "20140626", "20140703",
        #    "20140708", "20140730", "20140805", "20140819", "20140819", "20141019"]
      

      有关格式化指令,请参阅Kernel#sprintf。看来.map(&amp;:to_i) 实际上是不必要的;当使用d 指令时,Ruby 将表示整数的字符串视为整数。

      正则表达式/(\d+)\/(\d+)\/(\d+)/匹配一个或数字(月份),保存到捕获组1,然后是'/',然后是一个或数字(天),保存到捕获组2,后跟'/',后跟一个或数字(年份),它们被保存到捕获组 3。也可以这样写:

      /(\d{1,2})\/(\d{1,2})\/(\d{4})/
      

      或使用命名的捕获组:

      r = /(?<month>\d{1,2})\/(?<day>\d{1,2})\/(?<year>\d{4})/
      
      dates.sort_by do |d|
        d.sub(r) { "%4d%02d%02d" % [$~[:year], $~[:month], $~[:day]].map(&:to_i) }
      end.reverse
        #=> ["10/19/2014", "8/19/2014", "8/19/2014", "8/5/2014", "7/30/2014", "7/8/2014",
        #    "7/3/2014", "6/26/2014", "6/26/2014", "6/23/2014", "6/3/2014", "6/3/2014"]
      

      $~most recent MatchData object。它等于Regexp::last_match

      【讨论】:

        猜你喜欢
        • 2023-02-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-10-26
        相关资源
        最近更新 更多