Ruby 按升序和降序对多个值进行排序

Ruby 按升序和降序对多个值进行排序,ruby,sorting,Ruby,Sorting,我正在尝试根据不同的属性对对象数组进行排序。有些属性我想按升序排序,有些则按降序排序。我可以按升序或降序排序,但无法将两者结合起来 下面是我正在使用的简单类: class Dog attr_reader :name, :gender DOGS = [] def initialize(name, gender) @name = name @gender = gender DOGS << self end def self.all

我正在尝试根据不同的属性对对象数组进行排序。有些属性我想按升序排序,有些则按降序排序。我可以按升序或降序排序,但无法将两者结合起来

下面是我正在使用的简单类:

class Dog
  attr_reader :name, :gender

  DOGS = []

  def initialize(name, gender)
    @name = name
    @gender = gender
    DOGS << self
  end

  def self.all
    DOGS
  end

  def self.sort_all_by_gender_then_name
    self.all.sort_by { |d| [d.gender, d.name] }
  end
end
然后我可以使用sort\u all\u by\u gender\u then\u name方法

Dog.sort_all_by_gender_then_name
=> [@cocoa, @fluffy, @max, @rover]
它返回的数组首先包括雌性,然后是雄性,全部按名称升序排序

但是,如果我想让性别下降,然后名字上升,那么首先是男性,然后按名字上升排序。在这种情况下:

=> [@max, @rover, @cocoa, @fluffy]
或者,如果我想按性别升序,但按姓名降序:

=> [@fluffy, @cocoa, @rover, @max]

对数值进行排序时,可以在-前面加上前缀,使其反向排序。但是,我一直无法找到一种方法来使用字符串实现这一点。任何帮助或想法都将不胜感激。谢谢

这里有一种方法可以使用
.sort
而不是
。sort\u by

dogs = [
  { name: "Rover", gender: "Male" },
  { name: "Max", gender: "Male" },
  { name: "Fluffy", gender: "Female" },
  { name: "Cocoa", gender: "Female" }
]

# gender asc, name asc
p(dogs.sort do |a, b|
  [a[:gender], a[:name]] <=> [b[:gender], b[:name]]
end)

# gender desc, name asc
p(dogs.sort do |a, b|
  [b[:gender], a[:name]] <=> [a[:gender], b[:name]]
end)

# gender asc, name desc
p(dogs.sort do |a, b|
  [a[:gender], b[:name]] <=> [b[:gender], a[:name]]
end)
module ReversedOrder
  def <=>(other)
    - super
  end
end

基本上,这类似于对数字求反(正如您在问题中提到的),如果需要按降序排序,则将属性交换到另一个元素。

反向排序
mixin可以帮助您使用
sort\u by
在单独的属性上完成混合方向排序:

dogs = [
  { name: "Rover", gender: "Male" },
  { name: "Max", gender: "Male" },
  { name: "Fluffy", gender: "Female" },
  { name: "Cocoa", gender: "Female" }
]

# gender asc, name asc
p(dogs.sort do |a, b|
  [a[:gender], a[:name]] <=> [b[:gender], b[:name]]
end)

# gender desc, name asc
p(dogs.sort do |a, b|
  [b[:gender], a[:name]] <=> [a[:gender], b[:name]]
end)

# gender asc, name desc
p(dogs.sort do |a, b|
  [a[:gender], b[:name]] <=> [b[:gender], a[:name]]
end)
module ReversedOrder
  def <=>(other)
    - super
  end
end

注意:小心
dup
反向元件。否则,您将把比较反相器混入实际对象,而不仅仅是为
sort\u by
制作的键,它将永远产生反向比较。

性能不会因为多个
extend
而真的很差吗?我有疑问,关于
enum#sort
我仍然不理解的是,
结果如何帮助enum排序?3个值
-1,0,+1
如何帮助对枚举进行排序?@Priti,这与大多数语言的(C,C++)排序函数类似-如果希望第一个参数排在第二个参数之前,返回+1,如果希望它们以与列表中相同的顺序出现,则返回0,否则您希望第二个参数在前面,返回-1。@Priti,如果我误解了您的疑问,请告诉我。谢谢。。是的,我想知道。。是的,现在我知道它是怎么工作的了。
dogs = [
  { name: "Rover", gender: "Male" },
  { name: "Max", gender: "Male" },
  { name: "Fluffy", gender: "Female" },
  { name: "Cocoa", gender: "Female" }
]

dogs.sort_by {|e| [e[:gender], e[:name]] }
=> [{:name=>"Cocoa", :gender=>"Female"},
 {:name=>"Fluffy", :gender=>"Female"},
 {:name=>"Max", :gender=>"Male"},
 {:name=>"Rover", :gender=>"Male"}]

dogs.sort_by {|e| [e[:gender].dup.extend(ReversedOrder), e[:name]] }
=> [{:name=>"Max", :gender=>"Male"},
 {:name=>"Rover", :gender=>"Male"},
 {:name=>"Cocoa", :gender=>"Female"},
 {:name=>"Fluffy", :gender=>"Female"}]