Tengo una variedad de hashes:
[
{ :foo => 'foo', :bar => 2 },
{ :foo => 'foo', :bar => 3 },
{ :foo => 'foo', :bar => 5 },
]
Estoy tratando de ordenar esta matriz en orden descendente de acuerdo con el valor de :baren cada hash.
Estoy usando sort_bypara ordenar la matriz anterior:
a.sort_by { |h| h[:bar] }
Sin embargo, esto ordena la matriz en orden ascendente. ¿Cómo hago que se ordene en orden descendente?
Una solución fue hacer lo siguiente:
a.sort_by { |h| -h[:bar] }
Pero ese signo negativo no parece apropiado.

sort_by.reversees dramáticamente más eficiente que la respuesta actualmente aceptada. Creo que también aborda mejor la preocupación que mencionó anteriormente para "transmitir la intención del código". Además de eso, Tin Man ha actualizado su respuesta para la versión actual de ruby. Esta pregunta ha sido vista más de 15k veces. Si puede ahorrar incluso 1 segundo del tiempo de cada espectador, creo que vale la pena.Respuestas:
Siempre es esclarecedor hacer un punto de referencia en las diferentes respuestas sugeridas. Esto es lo que descubrí:
#! / usr / bin / ruby requiere 'punto de referencia' ary = [] 1000.times { ary << {: bar => rand (1000)} } n = 500 Benchmark.bm (20) do | x | x.report ("sort") {n.times {ary.sort {| a, b | b [: bar] <=> a [: bar]}}} x.report ("ordenar al revés") {n.times {ary.sort {| a, b | a [: bar] <=> b [: bar]} .reverse}} x.report ("sort_by -a [: bar]") {n.times {ary.sort_by {| a | -un bar] } } } x.report ("sort_by a [: bar] * - 1") {n.times {ary.sort_by {| a | a [: barra] * - 1}}} x.report ("sort_by.reverse!") {n.times {ary.sort_by {| a | a [: bar]} .reverse}} final sistema de usuario total real ordenar 3.960000 0.010000 3.970000 (3.990886) ordenar inverso 4.040000 0.000000 4.040000 (4.038849) sort_by -a [: bar] 0.690000 0.000000 0.690000 (0.692080) sort_by a [: bar] * - 1 0.700000 0.000000 0.700000 (0.699735) sort_by.reverse! 0.650000 0.000000 0.650000 (0.654447)Creo que es interesante que @ Pablo's
sort_by{...}.reverse!sea el más rápido. Antes de ejecutar la prueba, pensé que sería más lento que "-a[:bar]", pero negar el valor lleva más tiempo que invertir la matriz completa en una sola pasada. No es una gran diferencia, pero cada pequeña aceleración ayuda.Estos son los resultados para Ruby 1.9.3p194 (2012-04-20 revisión 35410) [x86_64-darwin10.8.0]:
Estos están en un viejo MacBook Pro. Las máquinas más nuevas o más rápidas tendrán valores más bajos, pero las diferencias relativas permanecerán.
Aquí hay una versión un poco actualizada en el hardware más nuevo y la versión 2.1.1 de Ruby:
Nuevos resultados ejecutando el código anterior usando Ruby 2.2.1 en un Macbook Pro más reciente. Una vez más, los números exactos no son importantes, son sus relaciones:
Actualizado para Ruby 2.7.1 en una MacBook Pro de mediados de 2015:
La fuente
Array#reversees:do *p2-- = *p1++; while (--len > 0);está copiando los punteros a los elementos en orden inverso si recuerdo mi C correctamente, por lo que la matriz se invierte.fuente
Solo una cosa rápida, que denota la intención de descender el orden.
(Pensará en una mejor manera mientras tanto);)
fuente
Podrías hacerlo:
fuente
sort_byfue que evitó correr la función de comparación tantas vecessort_byes mucho más eficiente y más legible. Negar el valor o hacer un reverso al final será más rápido y más legible.* -1no funciona con todos los valores (por ejemplo, Tiempo), yreversereordenará los valores que se ordenaron como igualesVeo que tenemos (junto a otros) básicamente dos opciones:
y
Si bien ambas formas le dan el mismo resultado cuando su clave de clasificación es única, tenga en cuenta que la
reverseforma invertirá el orden de las claves que son iguales .Ejemplo:
Si bien a menudo no necesita preocuparse por esto, a veces sí. Para evitar este comportamiento, puede introducir una segunda clave de clasificación (que seguramente debe ser única al menos para todos los elementos que tienen la misma clave de clasificación):
fuente
reversees diferente. Creo que también estropeará un tipo anterior, en el caso de que uno esté tratando de aplicar varios tipos en algún orden.Qué pasa:
¡¡Funciona!!
fuente
sortfuncionará, solo es más rápido al ordenar valores inmediatos. Si tienes que cavar por ellossort_byes más rápido. Ver el punto de referencia.Con respecto al conjunto de referencia mencionado, estos resultados también son válidos para las matrices ordenadas.
sort_by/reversees:Y los resultados:
fuente
La solución simple de ascendente a descendente y viceversa es:
INSTRUMENTOS DE CUERDA
DIGITOS
fuente
Para aquellas personas que les gusta medir la velocidad en IPS;)
Y resultados:
fuente