18

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

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

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

有什么建议么?

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

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

5 回答 5

33

怎么样:


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

于 2008-09-16T14:43:03.393 回答
8

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

要正常按 blah 和 craw 排序,但按相反顺序按 bleu 排序,请执行以下操作:

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

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

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

something.sort_by!{|a| [a.blah, -a.craw, a.bleu]}
于 2012-07-03T23:59:10.960 回答
4

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

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)]}
于 2008-09-16T15:21:55.780 回答
4

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"]]
于 2008-09-16T19:43:44.467 回答
2

我已经使用格伦的食谱有一段时间了。厌倦了一遍又一遍地从一个项目复制到另一个项目的代码,我决定把它变成一个宝石:

http://github.com/dadooda/invert

于 2010-07-18T10:31:51.830 回答