J'ai un tableau d'objets dans Ruby sur Rails. Je veux trier le tableau en fonction d'un attribut de l'objet. Est-ce possible?
Je recommande d'utiliser plutôt sort_by:
objects.sort_by {|obj| obj.attribute}
Surtout si l'attribut peut être calculé.
Ou une approche plus concise:
objects.sort_by(&:attribute)
Oui, en utilisant Array#sort!
c'est facile.
myarray.sort! { |a, b| a.attribute <=> b.attribute }
Ordre croissant :
objects_array.sort! { |a, b| a.attribute <=> b.attribute }
ou
objects_array.sort_by{ |obj| obj.attribute }
Ordre décroissant :
objects_array.sort! { |a, b| b.attribute <=> a.attribute }
ou
objects_array.sort_by{ |obj| obj.attribute }.reverse
au cas où vous auriez besoin de trier par deux attributs, où le premier est plus important que le second (signifie que le second argument est pris en compte uniquement si les premiers arguments sont égaux), vous pouvez procéder comme suit
myarray.sort{ |a,b| (a.attr1 == b.attr1) ? a.attr2 <=> b.attr2 : a.attr1 <=> b.attr1 }
ou en cas de tableau de tableaux
myarray.sort{ |a,b| (a[0] == b[0]) ? a[1] <=> b[1] : a[0] <=> b[0] }
Vous pouvez rendre n'importe quelle classe triable en redéfinissant la méthode <=>:
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
Maintenant, un tableau d'objets Person sera triable sur 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" ]
Le type de tableau # fonctionne bien, comme indiqué ci-dessus:
myarray.sort! { |a, b| a.attribute <=> b.attribute }
MAIS, vous devez vous assurer que le <=>
l'opérateur est implémenté pour cet attribut. S'il s'agit d'un type de données natif Ruby, ce n'est pas un problème. Sinon, écrivez votre propre implémentation qui renvoie -1 si a <b, 0 si elles sont égales et 1 si> b.
Plus élégant objects.sort_by(&:attribute)
, vous pouvez ajouter un .reverse
_ si vous devez modifier l'ordre.