如何按多个条件以不同的顺序排序?

时间:2020-03-05 18:56:09  来源:igfitidea点击:

我真的很想在没有猴子补丁的情况下进行处理,但是我还没有找到其他选择。

我有一个数组(在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

回答

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

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"]]

回答

我已经使用Glenn的食谱已有一段时间了。厌倦了一次又一次地在项目之间复制代码,我决定将它变成一颗宝石:

http://github.com/dadooda/invert