Ein Array von Objekten in Ruby nach Objektattributen sortieren?


128

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:


222

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)

81
Oder die Kurzfassung:objects.sort_by(&:attribute)
Nikola

3
noch kürzere objects.sort_by &: attribute
jasin_89

1
Wenn Sie Probleme mit der getrennten Sortierung von Groß- und Kleinbuchstaben haben, können Sieobjects.sort_by { |obj| obj.attribute.downcase }
campeterson

1
Irgendeine Idee, wie dies im Vergleich zu sort!(z. B. Geschwindigkeit usw.) ist?
Joshua Pinter


35

Ja, Array#sort!das ist einfach.

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

Danke Kumpel, aber es hat bei mir nicht geklappt. Ich habe eine Reihe von Objekten. In dem eines der Attribute des Objekts erstellt wird_at. Ich möchte es mit diesem Feld sortieren. Also habe ich @ comm_bytes.sort gemacht! {| a, b | a.created_at <=> b.created_at}, aber kein Glück für mich, kannst du helfen .... ??

4
Gibt es eine Methode "created_at" für den Zugriff auf das Attribut "@created_at"? Was für ein Objekt ist @created_at? Definiert es <=>? 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".
Rampion

es funktioniert, wenn Sie myarray = myarray.sort {...} ohne "!"
DoruChidean

@Doru Ja, das funktioniert auch, aber warum würdest du das tun? Es ist weniger direkt und weniger effizient. Verwenden sortSie 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, sortruft sort!intern, nachdem das ursprüngliche Objekt zu kopieren.
Konrad Rudolph

1
@Doru Es muss irgendwo anders im Code ein Fehler sein. Ich kann Ihnen zu 100% garantieren, dass er einwandfrei sort!funktioniert und immer (!) Das Gleiche tut, was Sie geschrieben haben.
Konrad Rudolph

27

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

20

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] }

14

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" ]

10

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.


10

Eleganter objects.sort_by(&:attribute)können Sie eine hinzufügen, .reversewenn Sie die Reihenfolge ändern müssen.



-2
@model_name.sort! { |a,b| a.attribute <=> b.attribute }

2
Es gibt viele identische Antworten aus dem Jahr 2009. Es ist nicht erforderlich, eine weitere hinzuzufügen.
Interjay

2
Nicht verwenden, sortwenn 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.
der Blechmann
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.