簡體   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