Ich habe eine Reihe von Objekten in Ruby on Rails. Ich möchte das Array nach einem Attribut des Objekts sortieren. Ist es möglich?
Ich habe eine Reihe von Objekten in Ruby on Rails. Ich möchte das Array nach einem Attribut des Objekts sortieren. Ist es möglich?
Antworten:
Ich empfehle stattdessen sort_by zu verwenden:
objects.sort_by {|obj| obj.attribute}
Besonders wenn Attribut berechnet werden kann.
Oder ein prägnanterer Ansatz:
objects.sort_by(&:attribute)
objects.sort_by { |obj| obj.attribute.downcase }
sort!
(z. B. Geschwindigkeit usw.) ist?
Ja, Array#sort!
das ist einfach.
myarray.sort! { |a, b| a.attribute <=> b.attribute }
<=>
? Welche Art von Fehlern bekommen Sie? etc, etc, ad nauseum. Mit anderen Worten, wir brauchen mehr Details als "aber kein Glück für mich".
sort
Sie diese Option, wenn Sie das Original beibehalten und das Ergebnis einem anderen Objekt zuweisen möchten. Andernfalls verwenden Sie die In-Place-Variante sort!
. In der Tat, sort
ruft sort!
intern, nachdem das ursprüngliche Objekt zu kopieren.
sort!
funktioniert und immer (!) Das Gleiche tut, was Sie geschrieben haben.
Aufsteigende Reihenfolge:
objects_array.sort! { |a, b| a.attribute <=> b.attribute }
oder
objects_array.sort_by{ |obj| obj.attribute }
Absteigende Reihenfolge :
objects_array.sort! { |a, b| b.attribute <=> a.attribute }
oder
objects_array.sort_by{ |obj| obj.attribute }.reverse
Wenn Sie nach zwei Attributen sortieren müssen, wobei das erste wichtiger als das zweite ist (dh, zweite Argumente werden nur berücksichtigt, wenn die ersten Argumente gleich sind), können Sie dies tun
myarray.sort{ |a,b| (a.attr1 == b.attr1) ? a.attr2 <=> b.attr2 : a.attr1 <=> b.attr1 }
oder im Falle eines Arrays von Arrays
myarray.sort{ |a,b| (a[0] == b[0]) ? a[1] <=> b[1] : a[0] <=> b[0] }
Sie können jede Klasse sortierbar machen, indem Sie die <=> -Methode überschreiben:
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
Jetzt kann ein Array von Personenobjekten nach Nachname sortiert werden.
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" ]
Array # sort funktioniert gut, wie oben angegeben:
myarray.sort! { |a, b| a.attribute <=> b.attribute }
ABER Sie müssen sicherstellen, dass der <=>
Operator für dieses Attribut implementiert ist. Wenn es sich um einen nativen Ruby-Datentyp handelt, ist dies kein Problem. Andernfalls schreiben Sie eine eigene Implementierung, die -1 zurückgibt, wenn a <b, 0, wenn sie gleich sind, und 1, wenn a> b.
Eleganter objects.sort_by(&:attribute)
können Sie eine hinzufügen, .reverse
wenn Sie die Reihenfolge ändern müssen.
@model_name.sort! { |a,b| a.attribute <=> b.attribute }
sort
wenn Sie Objekte sortieren, die nicht direkt verglichen werden können. Wenn Sie auf Attribute zugreifen oder eine Berechnung durchführen müssen, um den zu vergleichenden Wert zu erhalten sort_by
. Es wird viel schneller sein.
objects.sort_by(&:attribute)