¿Cómo puedo ordenar por varias condiciones con los diferentes órdenes?
Pregunta
Realmente me gustaría manejar esto sin monkey patching pero no he sido capaz de encontrar otra opción todavía.
Tengo un array (en Ruby) que necesito para ordenar por varias condiciones.Sé cómo usar el método de ordenación, y yo he usado el truco en la clasificación con una gran variedad de opciones para ordenar por varias condiciones.Sin embargo, en este caso me falta la primera condición para ordenar en forma ascendente y el segundo para ordenar descendente.Por ejemplo:
ordered_list = [[1, 2], [1, 1], [2, 1]]
Alguna sugerencia?
Editar:Acabo de darme cuenta de que debo mencionar que yo no puedo comparar fácilmente la primera y la segunda los valores (de hecho estoy trabajando con los atributos de los objetos aquí).Así que para un simple ejemplo es más como:
ordered_list = [[1, "b"], [1, "a"], [2, "a"]]
Solución
Cómo acerca de:
ordered_list = [[1, "b"], [1, "a"], [2, "a"]]
ordered_list.sort! do |a,b|
[a[0],b[1]] <=> [b[0], a[1]]
end
Otros consejos
Yo estaba teniendo una pesadilla de un tiempo tratando de averiguar cómo revertir tipo de un atributo específico, pero normalmente ordenar los otros dos.Sólo una nota acerca de la clasificación para aquellos que vienen después de esto y están confundidos por el |a,b| bloque de sintaxis.Usted puede utilizar el {|a,b| a.blah <=> b.blah}
estilo de bloque con sort_by!
o sort_by
.Debe ser utilizado con sort!
o sort
.También, como se indicó anteriormente por los otros carteles de intercambio a
y b
a través del operador de comparación <=>
para invertir el orden.Como este:
Para ordenar por bla, y craw normalmente, pero, por bleu en orden inverso hacer esto:
something.sort!{|a,b| [a.blah, b.bleu, a.craw] <=> [b.blah, a.bleu, b.craw]}
También es posible el uso de la -
firmar con sort_by
o sort_by!
para hacer un inversa de números (hasta donde yo soy consciente de que sólo funciona en los números de modo que no lo intente con las cuerdas, como se acaba de errores y mata a la página).
Asumir a.craw
es un número entero.Por ejemplo:
something.sort_by!{|a| [a.blah, -a.craw, a.bleu]}
Tuve este mismo problema básico, y resuelto por la adición de este:
class Inverter
attr_reader :o
def initialize(o)
@o = o
end
def <=>(other)
if @o.is && other.o.is
-(@o <=> other.o)
else
@o <=> other.o
end
end
end
Este es un contenedor que simplemente invierte la <=> la función, que permite hacer cosas como esta:
your_objects.sort_by {|y| [y.prop1,Inverter.new(y.prop2)]}
Enumerable#multisort
es una solución genérica que puede ser aplicado a las matrices de cualquier tamaño, no sólo a aquellos con 2 elementos.Los argumentos son valores booleanos que indican si un campo específico se deben ordenar de forma ascendente o descendente (de uso a continuación):
items = [
[3, "Britney"],
[1, "Corin"],
[2, "Cody"],
[5, "Adam"],
[1, "Sally"],
[2, "Zack"],
[5, "Betty"]
]
module Enumerable
def multisort(*args)
sort do |a, b|
i, res = -1, 0
res = a[i] <=> b[i] until !res.zero? or (i+=1) == a.size
args[i] == false ? -res : res
end
end
end
items.multisort(true, false)
# => [[1, "Sally"], [1, "Corin"], [2, "Zack"], [2, "Cody"], [3, "Britney"], [5, "Betty"], [5, "Adam"]]
items.multisort(false, true)
# => [[5, "Adam"], [5, "Betty"], [3, "Britney"], [2, "Cody"], [2, "Zack"], [1, "Corin"], [1, "Sally"]]
He estado usando Glenn receta durante bastante tiempo ahora.Cansado de copiar el código de un proyecto a otro, una y otra vez, me he decidido a hacer una joya: