[英]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.