繁体   English   中英

按日期排序数组元素

[英]Sorting array elements by date

我有以下数组。

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.

这样,例如 1/1/2014 就不会在 12/13/1994 之前出现。

我尝试了以下

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 Array Class sort_by 方法。 我想按日期格式排序,较新的日期在较早的日期之前。

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

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

预先感谢您的任何帮助。

尝试:

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

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

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

我不知道为什么您的预期输出只包含 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" > "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(&: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"]

$~最新的MatchData对象 它等于Regexp::last_match

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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