Sorting an array of objects in Ruby by object attribute?

后端 未结 9 696
渐次进展
渐次进展 2021-01-30 02:00

I have an array of objects in Ruby on Rails. I want to sort the array by an attribute of the object. Is it possible?

相关标签:
9条回答
  • 2021-01-30 02:23

    in case you need sorting by two attributes, where first one is more important then second (means taking in account second arguments only if first arguments are equal), then you may do like this

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

    or in case of array of arrays

    myarray.sort{ |a,b| (a[0] == b[0]) ? a[1] <=> b[1] : a[0] <=> b[0] }
    
    0 讨论(0)
  • 2021-01-30 02:24

    I recommend using sort_by instead:

    objects.sort_by {|obj| obj.attribute}
    

    Especially if attribute may be calculated.

    Or a more concise approach:

    objects.sort_by(&:attribute)
    
    0 讨论(0)
  • 2021-01-30 02:26

    More elegant objects.sort_by(&:attribute), you can add on a .reverse if you need to switch the order.

    0 讨论(0)
  • Array#sort works well, as posted above:

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

    BUT, you need to make sure that the <=> operator is implemented for that attribute. If it's a Ruby native data type, this isn't a problem. Otherwise, write you own implementation that returns -1 if a < b, 0 if they are equal, and 1 if a > b.

    0 讨论(0)
  • 2021-01-30 02:32

    Yes its possible

    http://ariejan.net/2007/01/28/ruby-sort-an-array-of-objects-by-an-attribute/

    0 讨论(0)
  • 2021-01-30 02:33

    You can make any class sortable by overriding the <=> method:

    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
    

    Now an array of Person objects will be sortable on 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" ]
    
    0 讨论(0)
提交回复
热议问题