我有一个包含空字符串的日期数组,我想用两种方式对其重新排序,每种情况下,空字符串应始终位于数组的前面。
[" ", "2018-10-01", "2019", " ", "2019-06-20", "2019-06", "2019-10", "2019-01-01", "2017", "2018-05", "2018", "2018-05-10", " "]
第一个结果就是以这种方式重新排序
["", "", "", "2019-10-01", "2019-10", "2019-06-20", "2019-06", "2019", "2018-01-01", "2018-05", "2018-05-10", "2017"]
我希望能够以这种方式重新排序的第二种方式:
[" ", " ", " ", "2017", "2018-01-01", "2019-06-20", "2019-06", "2019-10-01", "2019-10", "2019"]
我尝试了以下代码,但没有得到期望的结果。
["", "", "", "2019-10-01", "2019-10", "2019-06-20", "2019-06", "2019", "2018-01-01", "2018-05", "2018-05-10", "2017"].sort_by { |date| parts = date.split('-').map(&:to_i) }
更新
升序排序有可能以此顺序出现。 yy-mm-dd,然后是yy-mm,然后是年份,这意味着排序应采用这种形式
[" ", " ", " ", "2017","2018-05-10", "2018-05", "2018-10-01", "2018", "2019-01-01", "2019-06-20", "2019-06", "2019-10", "2019"]
。因此,它不是常规的升序排序,而是基于导致上述顺序的模式。
相同的模式适用于降序排列。
答案 0 :(得分:2)
arr = [" ", "2018-10-01", "2019", " ", "2019-06-20", "2019-06", "2019-10",
"2019-01-01", "2017", "2018-05", "2018", "2018-05-10", " "]
升序:
def sort_asc(arr)
arr.sort
end
sort_asc(arr)
#=> [" ", " ", " ",
# "2017",
# "2018", "2018-05", "2018-05-10", "2018-10-01",
# "2019", "2019-01-01", "2019-06", "2019-06-20", "2019-10"]
降序排列:
def sort_dsc(arr)
arr.sort_by { |s| s == ' ' ? '99' : s }.reverse
end
sort_dsc(arr)
#=> [" ", " ", " ",
# "2019-10", "2019-06-20", "2019-06", "2019-01-01", "2019",
# "2018-10-01", "2018-05-10", "2018-05", "2018",
# "2017"]
答案 1 :(得分:2)
您可以首先基于字符串是否为空的事实对列表进行分区。然后对所有当前日期进行排序,并将它们重新连接在一起。
dates = [" ", "2018-10-01", "2019", " ", "2019-06-20", "2019-06", "2019-10", "2019-01-01", "2017", "2018-05", "2018", "2018-05-10", " "]
asc = ->(a, b) { a <=> b }
desc = ->(a, b) { b <=> a }
blank, present = dates.partition(&:blank?)
result1 = blank + present.sort(&desc)
#=> [" ", " ", " ", "2019-10", "2019-06-20", "2019-06", "2019-01-01", "2019", "2018-10-01", "2018-05-10", "2018-05", "2018", "2017"]
result2 = blank + present.sort(&asc)
#=> [" ", " ", " ", "2017", "2018", "2018-05", "2018-05-10", "2018-10-01", "2019", "2019-01-01", "2019-06", "2019-06-20", "2019-10"]
注意:这只是根据字母顺序对数组进行排序。只要您使用yyyy-mm-dd
格式(如果只有一位,则使用零)就可以了。如果以其他格式提供日期,则您要先将其转换为日期。
strings = [" ", "2018-10-01", "2019", " ", "2019-06-20", "2019-06", "2019-10", "2019-01-01", "2017", "2018-05", "2018", "2018-05-10", " "]
array_to_date = lambda do |(year, month, day)|
month ||= 12
day ||= 31
begin
Date.new(year, month, day)
rescue ArgumentError
raise unless (1..12).cover? month
raise unless (1..31).cover? day
array_to_date.call([year, month, day - 1])
end
end
date_regex = /\A(\d{4})(?:-(\d{2})(?:-(\d{2}))?)?\z/
yyyy_mm_dd = ->(date_string) { date_regex.match(date_string).captures.compact.map(&:to_i) }
string_to_date = yyyy_mm_dd >> array_to_date
asc = ->(a, b) { string_to_date.call(a) <=> string_to_date.call(b) }
desc = ->(a, b) { string_to_date.call(b) <=> string_to_date.call(a) }
dates, non_dates = strings.partition(&date_regex.method(:match?))
result1 = non_dates + dates.sort(&desc)
#=> [" ", " ", " ", "2019", "2019-10", "2019-06", "2019-06-20", "2019-01-01", "2018", "2018-10-01", "2018-05", "2018-05-10", "2017"]
result2 = non_dates + dates.sort(&asc)
#=> [" ", " ", " ", "2017", "2018-05-10", "2018-05", "2018-10-01", "2018", "2019-01-01", "2019-06-20", "2019-06", "2019-10", "2019"]
注意:这不是最有效的解决方案,因为每次调用#sort
块时都必须转换字符串。如果使用大型数组,则可以先转换所有值,然后将它们保存在哈希中。然后在排序时查找它们。
当前的正则表达式还允许传递"0000-00-00"
之类的字符串,您可能想使其更加具体。