Ruby 中按多个条件排序
我有一个 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
似乎我必须实际上对两次单独的时间进行排序,而不是将所有内容都塞进该一个方法中。类似sort_by_category
,然后sort!
。最红宝石的方法是什么?
I have a collection of Post objects and I want to be able to sort them based on these conditions:
- First, by category (news, events, labs, portfolio, etc.)
- Then by date, if date, or by position, if a specific index was set for it
Some posts will have dates (news and events), others will have explicit positions (labs, and portfolio).
I want to be able to call posts.sort!
, so I've overridden <=>
, but am looking for the most effective way of sorting by these conditions. Below is a pseudo method:
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
It seems like I'd have to actually sort two separate times, rather than cramming everything into that one method. Something like sort_by_category
, then sort!
. What is the most ruby way to do this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您应该始终按照相同的标准进行排序,以确保顺序有意义。如果比较两个
nil
日期,position
可以判断顺序,但如果比较一个nil
日期与一组日期,你必须决定哪个先执行,无论位置如何(例如,将nil
映射到过去的一天)。否则想象一下以下情况:
根据您最初的标准,您将拥有: a < b< c<一个。那么,哪一个是最小的呢?
您还想立即进行排序。对于您的
<=>
实现,请使用#nonzero?
:如果您仅使用比较条件一次,或者该条件不通用,因此不希望要定义
<=>
,您可以将sort
与块一起使用:更好的是,有
sort_by
和sort_by!< /code> 您可以使用它来构建一个数组,以比较哪个优先级:
除了更短之外,使用
sort_by
的优点是您只能获得有序的条件。注意:
sort_by!
是在 Ruby 1.9.2 中引入的。您可以要求'backports/1.9.2/array/sort_by'
来使用与较老的红宝石一起使用。Post
不是ActiveRecord::Base
的子类(在这种情况下,您希望由数据库服务器完成排序)。You should always sort by the same criteria to insure a meaningful order. If comparing two
nil
dates, it is fine that theposition
will judge of the order, but if comparing onenil
date with a set date, you have to decide which goes first, irrespective of the position (for example by mappingnil
to a day way in the past).Otherwise imagine the following:
By your original criteria, you would have: a < b < c < a. So, which one is the smallest??
You also want to do the sort at once. For your
<=>
implementation, use#nonzero?
:If you use your comparison criteria just once, or if that criteria is not universal and thus don't want to define
<=>
, you could usesort
with a block:Better still, there is
sort_by
andsort_by!
which you can use to build an array for what to compare in which priority:Besides being shorter, using
sort_by
has the advantage that you can only obtain a well ordered criteria.Notes:
sort_by!
was introduced in Ruby 1.9.2. You canrequire 'backports/1.9.2/array/sort_by'
to use it with older Rubies.Post
is not a subclass ofActiveRecord::Base
(in which case you'd want the sort to be done by the db server).或者,您可以在数组中一次性进行排序,唯一的问题是处理其中一个属性为 nil 的情况,尽管如果您通过选择适当的 nil 保护了解数据集,仍然可以处理这种情况。此外,从您的伪代码中不清楚日期和位置比较是否按优先顺序或一个或另一个列出(即,如果存在其他使用位置,则使用日期)。第一个解决方案假设用途、类别,后跟日期,后跟位置
第二个假设它是日期或位置
Alternatively you could do the sort in one fell swoop in an array, the only gotcha is handling the case where one of the attributes is nil, although that could still be handled if you knew the data set by selecting the appropriate nil guard. Also it's not clear from your psuedo code if the date and position comparisons are listed in a priority order or an one or the other (i.e. use date if exists for both else use position). First solution assumes use, category, followed by date, followed by position
Second assumes it's date or position