我有以下数组.
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"]
Run Code Online (Sandbox Code Playgroud)
我们的数组存储10个字符串对象 为了按照我的方式对它们进行排序,我需要重新排列每个元素.
"2014/8/5", "2014/8/19", "2014/8/19", etc.
Run Code Online (Sandbox Code Playgroud)
这样,2014年1月1日就不会出现在12/13/1994之前.
我尝试了以下内容
dates.sort_by {|date|date.split(/[\/]/).rotate(-1).join('/')}
Run Code Online (Sandbox Code Playgroud)
我想按日期排序这个数组,最新的日期是第一个.
实际产出
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
Run Code Online (Sandbox Code Playgroud)
预期产出
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
Run Code Online (Sandbox Code Playgroud)
该解决方案涉及使用Ruby Array Class sort_by方法.我想用日期格式排序,其中较早的日期早于日期.
我的问题是,我将如何根据日期对数组进行排序.
如果这是一个愚蠢的问题,我很抱歉,但我搜索了这个网站,但找不到任何结果.
预先感谢您的任何帮助.
Bro*_*tse 10
尝试:
dates.sort_by { |s| Date.strptime(s, '%m/%d/%Y') }
Run Code Online (Sandbox Code Playgroud)
如果您希望从最新日期开始:
dates.sort_by { |s| Date.strptime(s, '%m/%d/%Y') }.reverse
Run Code Online (Sandbox Code Playgroud)
我不知道为什么您的预期输出只包含 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"
]
Run Code Online (Sandbox Code Playgroud)
我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"]
Run Code Online (Sandbox Code Playgroud)
这就是正在发生的事情。
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>
Run Code Online (Sandbox Code Playgroud)
如您所见,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]
Run Code Online (Sandbox Code Playgroud)
类似地,第三个元素enum被转换为:
"8/19/2014".split(?/).rotate(-1).map { |e| -e.to_i }
#=> [-2014, -8, -19]
Run Code Online (Sandbox Code Playgroud)
sort_by使用Array#<=>比较元素对。阅读该文档后,您将了解原因:
[-2014, -6, -23] <=> [-2014, -8, -19]
#=> 1
Run Code Online (Sandbox Code Playgroud)
这意味着"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"]
Run Code Online (Sandbox Code Playgroud)
注意
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"]
Run Code Online (Sandbox Code Playgroud)
arr.sort
#=> ["20140603", "20140603", "20140623", "20140626", "20140626", "20140703",
# "20140708", "20140730", "20140805", "20140819", "20140819", "20141019"]
Run Code Online (Sandbox Code Playgroud)
有关格式化指令,请参阅Kernel#sprintf。看来这.map(&:to_i)实际上是不必要的;当使用该d指令时,Ruby 将表示整数的字符串视为整数。
正则表达式/(\d+)\/(\d+)\/(\d+)/匹配一个或多个数字(月份),保存为捕获组 1,然后是'/',后跟一个或数字(日),保存为捕获组 2,然后是'/',后跟一个或数字(年),它们被保存到捕获组 3 中。也可以这样写:
/(\d{1,2})\/(\d{1,2})\/(\d{4})/
Run Code Online (Sandbox Code Playgroud)
或使用命名捕获组:
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"]
Run Code Online (Sandbox Code Playgroud)
$~是最近的MatchData对象。它等于Regexp::last_match。