Сортировка массива объектов в Ruby по атрибуту объекта?

У меня есть массив объектов в Ruby on Rails. Я хочу отсортировать массив по атрибуту объекта. Возможно ли это?

Ответ 1

Я рекомендую вместо этого использовать sort_by:

objects.sort_by {|obj| obj.attribute}

Особенно, если атрибут может быть рассчитан.

Или более краткий подход:

objects.sort_by(&:attribute)

Ответ 2

Да, используя Array#sort!, это легко.

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

Ответ 3

По возрастанию:

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

Ответ 4

если вам нужна сортировка по двум атрибутам, где первая важнее, а затем вторая (означает учет вторых аргументов, только если первые аргументы равны), тогда вы можете сделать это следующим образом:

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

Ответ 5

Вы можете сделать любой класс сортируемым, переопределив метод <=>:

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

Ответ 6

Array # sort работает хорошо, как указано выше:

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

НО, вам нужно убедиться, что для этого атрибута реализован оператор <=>. Если это родной тип данных Ruby, это не проблема. В противном случае напишите свою собственную реализацию, которая возвращает -1, если a < b, 0, если они равны, и 1, если a > b.

Ответ 7

Более элегантные objects.sort_by(&:attribute) вы можете добавить в .reverse если вам нужно .reverse порядок.

Ответ 8

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