Lan*_*ard 8 ruby sorting operators comparison-operators spacecraft-operator
我有一组Post对象,我希望能够根据这些条件对它们进行排序:
一些帖子将有日期(新闻和事件),其他帖子将有明确的职位(实验室和投资组合).
我希望能够打电话posts.sort!,所以我已经覆盖了<=>,但我正在寻找最有效的排序方式.以下是伪方法:
def <=>(other)
# first, everything is sorted into
# smaller chunks by category
self.category <=> other.category
# then, per category, by date or position
if self.date and other.date
self.date <=> other.date
else
self.position <=> other.position
end
end
Run Code Online (Sandbox Code Playgroud)
看起来我必须实际排序两次,而不是将所有内容都塞进那个方法中.那样的sort_by_category话sort!.最红宝石的方法是什么?
Mar*_*une 12
您应该始终按相同的标准排序,以确保有意义的订单.如果比较两个nil日期,position判断订单的判断是正常的,但如果将一个nil日期与设定日期进行比较,您必须决定哪个日期先行,而不管位置如何(例如通过映射nil到过去的日期) ).
否则想象如下:
a.date = nil ; a.position = 1
b.date = Time.now - 1.day ; b.position = 2
c.date = Time.now ; c.position = 0
Run Code Online (Sandbox Code Playgroud)
根据您的原始标准,您将拥有:a <b <c <a.那么,哪一个是最小的?
您还想立即进行排序.对于您的<=>实现,请使用#nonzero?:
def <=>(other)
return nil unless other.is_a?(Post)
(self.category <=> other.category).nonzero? ||
((self.date || AGES_AGO) <=> (other.date || AGES_AGO)).nonzero? ||
(self.position <=> other.position).nonzero? ||
0
end
Run Code Online (Sandbox Code Playgroud)
如果您只使用一次比较标准,或者该标准不是通用的,因此不想定义<=>,则可以使用sort块:
post_ary.sort{|a, b| (a.category <=> ...).non_zero? || ... }
Run Code Online (Sandbox Code Playgroud)
更妙的是,有sort_by和sort_by!您可以使用它来构建什么,其中优先级比较数组:
post_ary.sort_by{|a| [a.category, a.date || AGES_AGO, a.position] }
Run Code Online (Sandbox Code Playgroud)
除了缩短,使用sort_by的优势在于您只能获得良好的有序标准.
笔记:
sort_by!在Ruby 1.9.2中引入.您可以require 'backports/1.9.2/array/sort_by'将它与较旧的红宝石一起使用.Post不是子类ActiveRecord::Base(在这种情况下,您希望排序由db服务器完成).| 归档时间: |
|
| 查看次数: |
5561 次 |
| 最近记录: |