Ho una serie di oggetti in Ruby on Rails. Voglio ordinare l'array in base a un attributo dell'oggetto. È possibile?
Ho una serie di oggetti in Ruby on Rails. Voglio ordinare l'array in base a un attributo dell'oggetto. È possibile?
Risposte:
Consiglio invece di usare sort_by:
objects.sort_by {|obj| obj.attribute}
Soprattutto se l'attributo può essere calcolato.
O un approccio più conciso:
objects.sort_by(&:attribute)
objects.sort_by { |obj| obj.attribute.downcase }
sort!
(ad esempio velocità, ecc.)?
Sì, utilizzarlo Array#sort!
è facile.
myarray.sort! { |a, b| a.attribute <=> b.attribute }
<=>
? Che tipo di errori stai riscontrando? ecc. ecc. fino alla nausea. In altre parole, abbiamo bisogno di più dettagli di "ma non ho fortuna".
sort
se si desidera conservare l'originale e assegnare il risultato a un oggetto diverso; altrimenti, utilizzare la variante sul posto, sort!
. Infatti, sort
chiama sort!
internamente, dopo aver copiato l'oggetto originale.
sort!
funzionerà perfettamente e farai sempre (!) La stessa cosa di quello che hai scritto.
Ordine ascendente :
objects_array.sort! { |a, b| a.attribute <=> b.attribute }
o
objects_array.sort_by{ |obj| obj.attribute }
Ordine decrescente :
objects_array.sort! { |a, b| b.attribute <=> a.attribute }
o
objects_array.sort_by{ |obj| obj.attribute }.reverse
nel caso in cui sia necessario ordinare per due attributi, dove il primo è più importante del secondo (significa prendere in considerazione i secondi argomenti solo se i primi argomenti sono uguali), allora potresti fare così
myarray.sort{ |a,b| (a.attr1 == b.attr1) ? a.attr2 <=> b.attr2 : a.attr1 <=> b.attr1 }
o in caso di array di array
myarray.sort{ |a,b| (a[0] == b[0]) ? a[1] <=> b[1] : a[0] <=> b[0] }
Puoi rendere ordinabile qualsiasi classe sovrascrivendo il metodo <=>:
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
Ora un array di oggetti Person sarà ordinabile su 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" ]
Array # sort funziona bene, come pubblicato sopra:
myarray.sort! { |a, b| a.attribute <=> b.attribute }
MA, devi assicurarti che l' <=>
operatore sia implementato per quell'attributo. Se è un tipo di dati nativo di Ruby, questo non è un problema. Altrimenti, scrivi la tua implementazione che restituisca -1 se a <b, 0 se sono uguali e 1 se a> b.
Più elegante objects.sort_by(&:attribute)
, puoi aggiungere un .reverse
se devi cambiare l'ordine.
@model_name.sort! { |a,b| a.attribute <=> b.attribute }
sort
quando si ordinano oggetti che non possono essere confrontati direttamente. Se devi accedere agli attributi o eseguire un calcolo per ottenere il valore da confrontare, usa sort_by
. Sarà molto più veloce.
objects.sort_by(&:attribute)