Eu tenho uma matriz de objetos em Ruby on Rails. Eu quero classificar a matriz por um atributo do objeto. É possível?
Eu tenho uma matriz de objetos em Ruby on Rails. Eu quero classificar a matriz por um atributo do objeto. É possível?
Respostas:
Eu recomendo usar sort_by:
objects.sort_by {|obj| obj.attribute}
Especialmente se o atributo puder ser calculado.
Ou uma abordagem mais concisa:
objects.sort_by(&:attribute)
objects.sort_by { |obj| obj.attribute.downcase }
sort!
(por exemplo, velocidade, etc.)?
Sim, Array#sort!
é fácil usar isso.
myarray.sort! { |a, b| a.attribute <=> b.attribute }
<=>
? Que tipo de erros você está recebendo? etc, etc, ad nauseum. Em outras palavras, precisamos de mais detalhes do que "mas sem sorte para mim".
sort
se desejar preservar o original e atribuir o resultado a um objeto diferente; caso contrário, use a variante no local sort!
,. De fato, sort
chama sort!
internamente, depois de copiar o objeto original.
sort!
irá funcionar bem e sempre (!) Fará a mesma coisa que você escreveu.
Ordem ascendente :
objects_array.sort! { |a, b| a.attribute <=> b.attribute }
ou
objects_array.sort_by{ |obj| obj.attribute }
Ordem decrescente :
objects_array.sort! { |a, b| b.attribute <=> a.attribute }
ou
objects_array.sort_by{ |obj| obj.attribute }.reverse
caso você precise classificar por dois atributos, onde o primeiro é mais importante que o segundo (significa considerar os segundos argumentos apenas se os primeiros argumentos forem iguais), faça o seguinte
myarray.sort{ |a,b| (a.attr1 == b.attr1) ? a.attr2 <=> b.attr2 : a.attr1 <=> b.attr1 }
ou no caso de matriz de matrizes
myarray.sort{ |a,b| (a[0] == b[0]) ? a[1] <=> b[1] : a[0] <=> b[0] }
Você pode classificar qualquer classe substituindo o método <=>:
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
Agora, uma matriz de objetos Pessoa poderá ser classificada em 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" ]
A matriz # sort funciona bem, conforme publicado acima:
myarray.sort! { |a, b| a.attribute <=> b.attribute }
MAS, você precisa garantir que o <=>
operador esteja implementado para esse atributo. Se for um tipo de dados nativo do Ruby, isso não é um problema. Caso contrário, escreva sua própria implementação que retornará -1 se a <b, 0 se forem iguais e 1 se a> b.
Mais elegante objects.sort_by(&:attribute)
, você pode adicionar um .reverse
se precisar alterar o pedido.
@model_name.sort! { |a,b| a.attribute <=> b.attribute }
sort
ao classificar objetos que não podem ser comparados diretamente. Se você precisar acessar atributos ou fazer um cálculo para obter o valor para comparar o uso sort_by
. Será muito mais rápido.
objects.sort_by(&:attribute)