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 :bar
en cada hash.
Estoy usando sort_by
para 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.reverse
es 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í:
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#reverse
es: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_by
fue que evitó correr la función de comparación tantas vecessort_by
es 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.* -1
no funciona con todos los valores (por ejemplo, Tiempo), yreverse
reordenará 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
reverse
forma 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
reverse
es 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
sort
funcionará, solo es más rápido al ordenar valores inmediatos. Si tienes que cavar por ellossort_by
es 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
/reverse
es: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