У мене є масив об’єктів у Ruby on Rails. Я хочу сортувати масив за атрибутом об’єкта. Це можливо?
У мене є масив об’єктів у Ruby on Rails. Я хочу сортувати масив за атрибутом об’єкта. Це можливо?
Відповіді:
Я рекомендую натомість використовувати sort_by:
objects.sort_by {|obj| obj.attribute}
Особливо, якщо атрибут може бути обчислений.
Або більш стислий підхід:
objects.sort_by(&:attribute)
objects.sort_by { |obj| obj.attribute.downcase }
sort!
(наприклад, швидкість тощо)?
Так, використовувати Array#sort!
це легко.
myarray.sort! { |a, b| a.attribute <=> b.attribute }
<=>
? Які помилки ви отримуєте? тощо тощо, ad nauseum. Іншими словами, нам потрібно більше деталей, ніж "але мені не пощастило".
sort
якщо ви хочете зберегти оригінал та призначити результат іншому об'єкту; в іншому випадку використовуйте варіант в місці, sort!
. Фактично, sort
дзвінки sort!
внутрішньо, після копіювання оригінального об'єкта.
sort!
буде добре, і завжди (!) Робити те саме, що ви написали.
В порядку зростання :
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
якщо вам потрібне сортування за двома атрибутами, де перший важливіший, ніж другий (означає врахування другого аргументу, лише якщо перші аргументи рівні), ви можете зробити це так
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] }
Ви можете зробити будь-який клас сортування за допомогою методу <=>:
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 буде сортувати за прізвищем.
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" ]
Масив # сортування працює добре, як зазначено вище:
myarray.sort! { |a, b| a.attribute <=> b.attribute }
АЛЕ, вам потрібно переконатися, що <=>
оператор реалізований для цього атрибута. Якщо це рідний тип даних Ruby, це не проблема. В іншому випадку напишіть власну реалізацію, яка повертає -1, якщо a <b, 0, якщо вони рівні, і 1, якщо a> b.
@model_name.sort! { |a,b| a.attribute <=> b.attribute }
sort
коли ви сортуєте об'єкти, які неможливо порівняти безпосередньо. Якщо вам потрібно отримати доступ до атрибутів або зробити обчислення, щоб отримати значення для порівняння використання sort_by
. Це буде набагато швидше.
objects.sort_by(&:attribute)