ruby-on-rails 当end data有时为nil时,如何按end date对Ruby on Rails活动记录对象数组进行排序?

56lgkhnf  于 2023-03-04  发布在  Ruby
关注(0)|答案(3)|浏览(118)

我有一个Foo模型,它有很多属性,一个是:end_date,一个是:start_date,有时结束日期值为nil。
我想先按end_date,然后按start_date降序对这个数组排序,所有的end_datenil值都应该排在第一位。
因此,如果我有四个对象:

  • 对象A具有end_datenilstart_date,日期为2021年1月,
  • 对象B具有end_datenilstart_date,日期为2022年1月,
  • 对象C具有2022年12月的end_date和2022年1月的start_date
  • 对象D具有2021年12月的end_date和2021年1月的start_date

那么排序的顺序应该是[B, A, C, D],怎么做呢

jfgube3f

jfgube3f1#

foo_array.sort_by { |f| [f.end_date.nil? ? 0 : 1, f.end_date.to_i, f.start_date.to_i] }.reverse
  • 零三元组将确保这些是第一个
  • 将end_date / start_date转换为整数将确保它们的顺序
  • 那么调用reverse将给予降序
gojuced7

gojuced72#

如果您可以执行SQL查询,那么下面的代码应该对您有效。

Foo.order('start_date IS NOT NULL, start_date DESC')

另一方面,如果您已经有了物化数组,则可以执行以下操作。

arr = Array of Foos
arr.sort_by { |a, b| a.start_date && b.start_date ? a.start_date <=> b.start_date : a.start_date ? 1 : -1 }

对end_date重复相同的过程

txu3uszq

txu3uszq3#

使用#sort的单遍
a)使用块排序

# Using sort method
sorted = entries.sort do |a,b|
  # 1, 0 , -1 or nil
  comparison_result = a.end_date <=> b.end_date

  if comparison_result.nil?
    # nil follows a date
    a.end_date.nil? ? 1 : -1
  elsif comparison_result.zero?
    # end_dates are equal, compare start_dates instead
    a.start_date <=> b.start_date
  else
      comparison_result
  end.* -1 # descending order
end

B)将自定义比较方法添加到您的模型或模块中,然后执行以下操作

sorted = entries.sort do |a,b|
    a.compare_using_dates b
end

class Foo
  def compare_using_dates(other)
    comparison_result = end_date <=> other.end_date

    # nil result means one of the records has a nil end_date, so the end_dates are not equal
    if comparison_result.nil?
      end_date.nil? ? 1 : -1
    elsif comparison_result.zero?
      # end_dates are equal, compare start_dates instead
      start_date <=> other.start_date
    else
      comparison_result
    end.* -1
  end
end

相关问题