如何根据不同订单的多个条件进行排序?

我真的很想在没有猴子修补的情况下处理这个问题,但我还没有找到另一种选择。

我有一个数组(在Ruby中),我需要按多个条件排序。 我知道如何使用sort方法,我已经使用了一个选项数组进行排序的技巧,可以按多个条件排序。 但是,在这种情况下,我需要第一个条件来升序,第二个条件降序排序。 例如:

ordered_list = [[1, 2], [1, 1], [2, 1]] 

有什么建议?

编辑:刚才意识到我应该提到我不能轻易比较第一个和第二个值(我实际上是在使用对象属性)。 所以对于一个简单的例子,它更像是:

 ordered_list = [[1, "b"], [1, "a"], [2, "a"]] 

怎么样:

ordered_list = [[1, "b"], [1, "a"], [2, "a"]] ordered_list.sort! do |a,b| [a[0],b[1]] <=> [b[0], a[1]] end
ordered_list = [[1, "b"], [1, "a"], [2, "a"]] ordered_list.sort! do |a,b| [a[0],b[1]] <=> [b[0], a[1]] end 

我正在做一个噩梦,试图找出如何反向排序特定属性,但通常对其他两个进行排序。 只是关于那些在此之后出现并且被| a,b |混淆的排序的注释 块语法。 你不能使用{|a,b| a.blah <=> b.blah} {|a,b| a.blah <=> b.blah}使用sort_by!阻止样式sort_by!sort_by 。 它必须与sort!一起使用sort!sort 。 此外,如前面其他海报所示,在比较运算符<=>之间交换ab以反转排序顺序。 像这样:

要通过blah和craw正常排序,但按相反的顺序按蓝色排序,请执行以下操作:

 something.sort!{|a,b| [a.blah, b.bleu, a.craw] <=> [b.blah, a.bleu, b.craw]} 

也可以在sort_bysort_by!使用-符号sort_by! 对数字进行反向排序(据我所知,它只适用于数字,所以不要尝试使用字符串,因为它只是错误并杀死页面)。

假设a.craw是一个整数。 例如:

 something.sort_by!{|a| [a.blah, -a.craw, a.bleu]} 

我有同样的基本问题,并通过添加以下内容解决了这个问题:

 class Inverter attr_reader :o def initialize(o) @o = o end def <=>(other) if @o.is && other.o.is -(@o <=> other.o) else @o <=> other.o end end end 

这是一个简单地反转<=>函数的包装器,然后允许你做这样的事情:

 your_objects.sort_by {|y| [y.prop1,Inverter.new(y.prop2)]} 

Enumerable#multisort是一种通用解决方案,可应用于任何大小的数组,而不仅仅是那些包含2个项目的数组。 参数是布尔值,表示特定字段是按升序还是降序排序(使用如下):

 items = [ [3, "Britney"], [1, "Corin"], [2, "Cody"], [5, "Adam"], [1, "Sally"], [2, "Zack"], [5, "Betty"] ] module Enumerable def multisort(*args) sort do |a, b| i, res = -1, 0 res = a[i] <=> b[i] until !res.zero? or (i+=1) == a.size args[i] == false ? -res : res end end end items.multisort(true, false) # => [[1, "Sally"], [1, "Corin"], [2, "Zack"], [2, "Cody"], [3, "Britney"], [5, "Betty"], [5, "Adam"]] items.multisort(false, true) # => [[5, "Adam"], [5, "Betty"], [3, "Britney"], [2, "Cody"], [2, "Zack"], [1, "Corin"], [1, "Sally"]] 

我一直在使用格伦的配方已有一段时间了。 厌倦了一遍又一遍地将代码从一个项目复制到另一个项目,我决定把它变成一个gem:

http://github.com/dadooda/invert