J'ai un tableau d'objets dans Ruby on Rails. Je veux trier le tableau par un attribut de l'objet. C'est possible?
J'ai un tableau d'objets dans Ruby on Rails. Je veux trier le tableau par un attribut de l'objet. C'est possible?
Réponses:
Je recommande d'utiliser sort_by à la place:
objects.sort_by {|obj| obj.attribute}
Surtout si l'attribut peut être calculé.
Ou une approche plus concise:
objects.sort_by(&:attribute)
objects.sort_by { |obj| obj.attribute.downcase }
sort!
(par exemple, la vitesse, etc.)?
Oui, Array#sort!
il est facile de l'utiliser.
myarray.sort! { |a, b| a.attribute <=> b.attribute }
<=>
? Quel genre d'erreurs obtenez-vous? etc, etc, ad nauseum. En d'autres termes, nous avons besoin de plus de détails que "mais pas de chance pour moi".
sort
si vous souhaitez conserver l'original et affecter le résultat à un objet différent; sinon, utilisez la variante en place, sort!
. En fait, sort
appelle en sort!
interne, après avoir copié l'objet d'origine.
sort!
cela fonctionnera très bien, et toujours (!) Faire la même chose que ce que vous avez écrit.
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 ne prendre en compte les seconds arguments que si les premiers arguments sont égaux), alors vous pouvez faire comme ceci
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 remplaçant 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
Désormais, un tableau d'objets Person pourra être trié 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 tri de tableau fonctionne bien, comme indiqué ci-dessus:
myarray.sort! { |a, b| a.attribute <=> b.attribute }
MAIS, vous devez vous assurer que 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 a> b.
Plus élégant objects.sort_by(&:attribute)
, vous pouvez en ajouter un .reverse
si vous avez besoin de changer de commande.
@model_name.sort! { |a,b| a.attribute <=> b.attribute }
sort
lorsque vous triez des objets qui ne peuvent pas être directement comparés. Si vous devez accéder à des attributs ou faire un calcul pour obtenir la valeur à comparer, utilisez sort_by
. Ce sera beaucoup plus rapide.
objects.sort_by(&:attribute)