在Ruby中按对象属性对对象数组进行排序?


128

我在Ruby on Rails中有一个对象数组。我想按对象的属性对数组进行排序。可能吗?

Answers:


222

我建议改用sort_by:

objects.sort_by {|obj| obj.attribute}

特别是如果可以计算属性。

或更简洁的方法:

objects.sort_by(&:attribute)

81
还是速记版本:objects.sort_by(&:attribute)
Nikola

3
甚至更短的
object.sort_by

1
如果您对大写和小写字母分别排序有疑问,可以使用objects.sort_by { |obj| obj.attribute.downcase }
campeterson 2014年

1
知道这与sort!(例如速度等)相比如何吗?
约书亚·品特


35

是的,使用Array#sort!它很容易。

myarray.sort! { |a, b|  a.attribute <=> b.attribute }

Thnx哥们,但对我来说没有用,我有很多对象。在其中创建对象的属性之一。我想用此字段对其进行排序。所以我做了@ comm_bytes.sort!{| a,b | a.created_at <=> b.created_at},但我没有运气可以帮助.... ??

4
是否存在created_at方法来访问@created_at属性?@created_at是哪种对象?它定义了<=>吗?您遇到什么样的错误?等等,等等。换句话说,我们需要比“但对我没有运气”更多的细节。
风铃草

如果您执行myarray = myarray.sort {...},而不使用“!”,则此方法有效
DoruChidean '16

@Doru是的,也可以,但是为什么要这么做呢?它的直接性和效率较低。使用sort,如果你想保留原始和分配结果不同的对象; 否则,请使用就地变体sort!。实际上,在复制原始对象之后,内部sort调用sort!
康拉德·鲁道夫

1
@Doru代码中的其他地方肯定有错误,我可以100%保证您sort!可以正常工作,并且始终(!)所做的事情与您编写的内容相同。
康拉德·鲁道夫

27

升序:

objects_array.sort! { |a, b|  a.attribute <=> b.attribute }

要么

objects_array.sort_by{ |obj| obj.attribute }

降序 :

objects_array.sort! { |a, b|  b.attribute <=> a.attribute }

要么

objects_array.sort_by{ |obj| obj.attribute }.reverse

20

如果您需要按两个属性进行排序,第一个属性比第二个属性重要(意味着仅在第一个参数相等的情况下才考虑第二个参数),那么您可以这样做

myarray.sort{ |a,b| (a.attr1 == b.attr1) ? a.attr2 <=> b.attr2 : a.attr1 <=> b.attr1 }

或在数组数组的情况下

myarray.sort{ |a,b| (a[0] == b[0]) ? a[1] <=> b[1] : a[0] <=> b[0] }

14

您可以通过覆盖<=>方法使任何类可排序:

class Person

  attr_accessor :first_name, :last_name

  def initialize(first_name, last_name)
    @first_name = first_name
    @last_name = last_name
  end

  def <=>(other)
    @last_name + @first_name <=> other.last_name + other.first_name
  end

end

现在,一个Person对象数组可以在last_name上排序。

ar = [Person.new("Eric", "Cunningham"), Person.new("Homer", "Allen")]

puts ar  # => [ "Eric Cunningham", "Homer Allen"]  (Person objects!)

ar.sort!

puts ar  # => [ "Homer Allen", "Eric Cunningham" ]

10

Array#sort运作良好,如上所述:

myarray.sort! { |a, b|  a.attribute <=> b.attribute }

但是,您需要确保<=>对该属性实施了运算符。如果它是Ruby本机数据类型,那么这不是问题。否则,编写您自己的实现,如果a <b,则返回-1;如果相等,则返回0;如果a> b,则返回1。




-2
@model_name.sort! { |a,b| a.attribute <=> b.attribute }

2
2009年发布了许多相同的答案。无需添加其他答案。
Interjay

2
sort对无法直接比较的对象进行排序时,请勿使用。如果您必须访问属性或进行计算以获取要比较的值,请使用sort_by。它将更快。
Tin Man
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.