Ruby sort_by多个字段,可能包含nil值

时间:2016-04-15 05:41:04

标签: ruby-on-rails ruby

我想对哈希数组进行排序,其中每个哈希都有两个属性created_timeupdated_time。并且这些属性的值可以是datestring或nil。我希望它首先按created_time(ASC)和updated_time(ASC)排序。我尝试使用sort_by方法,但我无法指定多个键的条件,如Table中建议的排序方法。

created_time和updated_time这两个属性应按升序排序,空值为最后一个

假设数组是

[
 {"created_time" => nil, "updated_time" => "2016-04-10"},
 {"created_time" => nil, "updated_time" => "2016-04-09"},
 {"created_time" => "2016-04-15", "updated_time" => nil}
]

我希望结果为

[
 {"created_time"=>"2016-04-15", "updated_time"=>nil}, 
 {"created_time"=>nil, "updated_time"=>"2016-04-09"}, 
 {"created_time"=>nil, "updated_time"=>"2016-04-10"}
]

怎么办?

2 个答案:

答案 0 :(得分:0)

假设arr是一个哈希{"created_time"=>ct, "updated_time"=>ut}数组,其中ctut)是一个带有fomat“yyyy-mm-dd”或{{1}的日期字符串}}。设nil为日期字符串,保证晚于任何日期字符串值far_away_timect。例如,ut。然后,您可以使用Enumerable #sort_by进行排序,如下所示:

far_away_time = "3000-01-01"

由于datetrings采用ISO 8601格式,因此无需将它们转换为arr.sort_by do |h| ct, ut = h.values case [ct.nil?, ut.nil?] when [true, true] then [far_away_time, far_away_time, far_away_time] when [true, false] then [far_away_time, far_away_time, ut] when [false, true] then [far_away_time, ct, far_away_time] else [ct, ut, ""] end end 个对象(即,可以对字符串本身进行排序)。例如,Date。有关如何排序数组的说明,请参阅Array#<=>的文档。

我正在排序为一个三元素数组,以便哈希"2016-03-12" < "2016-03-13" #=> true{"created_time"=>"2016-01-01", "updated_time"=>nil}{"created_time"=>nil, "updated_time"=>"2016-01-01"}按照我列出的顺序排序(并放在排序的末尾)数组)。

答案 1 :(得分:0)

很抱歉问题不明确。我只想按升序对两个键的哈希数组进行排序,这些键可以有nil值。我想出了方法

     def date_time datestring
      DateTime.parse(datestring)
     end

    result = array_to_sort.sort do |a,b|  
     (a["created_time"] && b["created_time"] && a["updated_time"] && b["updated_time"]) ? [ date_time(a["created_time"]), date_time(a["updated_time"])] <=>  [ date_time(b["created_time"]), date_time(b["updated_time"])] : [ a["created_time"] && b["created_time"] ? date_time(a["created_time"]) : a["created_time"] ? -1 : 1,  a["updated_time"] && b["updated_time"] ? date_time(a["updated_time"]) : a["updated_time"] ? -1 : 1] <=>  [ a["created_time"] && b["created_time"] ? date_time(b["created_time"]) : b["created_time"] ? -1 : 1,  a["updated_time"] && b["updated_time"] ? date_time(b["updated_time"]) : b["updated_time"] ? -1 : 1]
    end