Sorting an array of objects in Ruby by object attribute?

RubySortingObject

Ruby Problem Overview


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?

Ruby Solutions


Solution 1 - Ruby

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)

Solution 2 - Ruby

Yes, using Array#sort! this is easy.

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

Solution 3 - Ruby

Ascending order :

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

or

objects_array.sort_by{ |obj| obj.attribute }

Descending order :

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

or

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

Solution 4 - Ruby

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

Solution 5 - Ruby

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

Solution 6 - Ruby

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

Solution 7 - Ruby

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.

Solution 8 - Ruby

Solution 9 - Ruby

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSatyam GautamView Question on Stackoverflow
Solution 1 - RubyScottView Answer on Stackoverflow
Solution 2 - RubyKonrad RudolphView Answer on Stackoverflow
Solution 3 - Rubyshiva kumarView Answer on Stackoverflow
Solution 4 - RubybumbuView Answer on Stackoverflow
Solution 5 - Rubyuser1182000View Answer on Stackoverflow
Solution 6 - RubyNoah DavisView Answer on Stackoverflow
Solution 7 - RubycjsView Answer on Stackoverflow
Solution 8 - RubyJohnno NolanView Answer on Stackoverflow
Solution 9 - RubyHarisankar P SView Answer on Stackoverflow