Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby中的多条件排序_Ruby_Sorting_Operators_Comparison Operators_Spacecraft Operator - Fatal编程技术网

Ruby中的多条件排序

Ruby中的多条件排序,ruby,sorting,operators,comparison-operators,spacecraft-operator,Ruby,Sorting,Operators,Comparison Operators,Spacecraft Operator,我有一个Post对象集合,我希望能够根据以下条件对它们进行排序: 首先,按类别(新闻、事件、实验室、投资组合等) 然后按日期(如果是日期)或按位置(如果为其设置了特定索引) 一些帖子会有日期(新闻和事件),其他帖子会有明确的位置(实验室和投资组合) 我希望能够调用posts.sort,所以我已经覆盖了,但是我正在寻找根据这些条件进行排序的最有效的方法。下面是一个伪方法: def <=>(other) # first, everything is sorted into

我有一个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
def(其他)
#首先,每件事都被分类
#按类别划分的小块
自我类别其他类别
#然后,按类别、日期或职位
如果self.date和other.date
self.date其他日期
其他的
自我定位
结束
结束

看起来我实际上必须对两个不同的时间进行排序,而不是将所有内容都塞进一个方法中。类似于
sort\u by\u category
,然后
sort。最简单的方法是什么?

您应该始终按照相同的标准进行排序,以确保有意义的顺序。如果比较两个
nil
日期,则
位置可以判断顺序,但如果将一个
nil
日期与一个设定日期进行比较,则必须决定哪个日期先到,而不考虑位置(例如,通过将
nil
映射到过去的日期)

否则,想象一下:

a.date = nil                   ; a.position = 1
b.date = Time.now - 1.day      ; b.position = 2
c.date = Time.now              ; c.position = 0
根据您最初的标准,您将有:a 您还希望立即进行排序。对于
实现,请使用
#非零?

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
更好的是,还有
排序依据
排序依据可用于构建阵列以比较哪个优先级的内容:

post_ary.sort_by{|a| [a.category, a.date || AGES_AGO, a.position] }
使用
sort_by
除了较短之外,还有一个优点,即您只能获得有序的标准

注:

  • 排序依据是在Ruby 1.9.2中引入的。你可以把它和老红宝石一起使用
  • 我假设
    Post
    不是
    ActiveRecord::Base
    的子类(在这种情况下,您希望由db服务器完成排序)

或者,您可以在数组中一下子进行排序,唯一的问题是处理其中一个属性为nil的情况,尽管如果您通过选择适当的nil保护知道数据集,仍然可以处理该情况。此外,从您的psuedo代码中也不清楚日期和职位比较是按优先级顺序列出的,还是按优先级顺序列出的(即,如果两个职位都有使用日期,则使用日期)。第一个解决方案假定使用、类别、日期和位置

def <=>(other)
    [self.category, self.date, self.position] <=> [other.category, other.date, other.position]
end
def(其他)
[self.category,self.date,self.position][other.category,other.date,other.position]
结束
第二个假设是日期或位置

def <=>(other)
    if self.date && other.date
        [self.category, self.date] <=> [other.category, other.date]
    else
        [self.category, self.position] <=> [other.category, other.position]
    end
end
def(其他)
如果self.date&&other.date
[self.category,self.date][other.category,other.date]
其他的
[self.category,self.position][other.category,other.position]
结束
结束

谢谢,我不知道
数字#非零?
-方法返回非布尔值不是有点奇怪吗?@Mladen:是的,但非常有用。另一个例子是,您可能期望一个
true/false
String
返回
nil
,而不是
false
。这有点误导:
post_ary.sort_by{a,b |(a.category…}
sort_by不接受带有两个参数的块。对于更复杂的排序问题,您应该返回一个数组。。也就是说:
post|ary.sort|u by{| a |[a.category,a.date,a.position]}
@TimoLehto:当然,谢谢你指出我的错误。相应地进行了编辑。为什么id为:。非零?| |0当您需要此| | 0Ah时是否有特殊条件,忘记了日期的
nil
。这种排序顺序没有很好地排序(请参阅我更新的答案)。就我的学习而言,你说它没有很好地排序是什么意思?对于一个有根据的顺序,以下内容始终适用:
a
意味着
a
。请参见我的答案,以获取一个与此标准不符的示例。但是,您可以通过对第一种情况进行以下调整来获得该示例:[self.category,self.date | AGES | u AGO,self.position][other.category,other.date | AGES | u AGO,other.position]来使用您的命名,对吗,不那么优雅,但是没有额外的检查结果是一样的,这样使用数组是很好的。但是速度会慢一些,特别是当需要计算某些字段时(例如,
#position
是一种进行某些计算的方法),但会产生相同的结果。
def <=>(other)
    if self.date && other.date
        [self.category, self.date] <=> [other.category, other.date]
    else
        [self.category, self.position] <=> [other.category, other.position]
    end
end