Сортировка массива объектов в Ruby по атрибуту объекта? - PullRequest
110 голосов
/ 19 мая 2009

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

Ответы [ 9 ]

188 голосов
/ 20 мая 2009

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

objects.sort_by {|obj| obj.attribute}

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

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

objects.sort_by(&:attribute)
33 голосов
/ 19 мая 2009

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

myarray.sort! { |a, b|  a.attribute <=> b.attribute }
26 голосов
/ 04 августа 2016

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

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
18 голосов
/ 16 февраля 2012

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

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] }
12 голосов
/ 20 мая 2012

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

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" ]
9 голосов
/ 19 мая 2009

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

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

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

8 голосов
/ 17 октября 2016

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

0 голосов
/ 06 марта 2013
@model_name.sort! { |a,b| a.attribute <=> b.attribute }
0 голосов
/ 19 мая 2009
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...