2010-11-24 44 views
56

Mi entrada de hash: h = { "a" => 20, "b" => 30, "c" => 10 }descendente ordenar por valor de un hash en Ruby

ascendente en orden: h.sort {|a,b| a[1]<=>b[1]} #=> [["c", 10], ["a", 20], ["b", 30]]

Pero, necesito [["b", 30], ["a", 20], ["c", 10]]

Cómo es si podemos hacer que funcione a la inversa, ¿Qué significa <=>?

Respuesta

151

Puede tenerlo más limpio, más claro y más rápido, ¡todo a la vez! De esta manera:

h.sort_by {|k,v| v}.reverse 

I como punto de referencia los tiempos en 3000 iteraciones de clasificación de un hash de 1000 elementos con valores aleatorios, y tengo estos tiempos:

h.sort {|x,y| -(x[1]<=>y[1])} -- 16.7s 
h.sort {|x,y| y[1] <=> x[1]} -- 12.3s 
h.sort_by {|k,v| -v} -- 5.9s 
h.sort_by {|k,v| v}.reverse -- 3.7 
+2

Visualmente, esto es más limpio pero provoca un recorrido extra de la colección para revertirlo. –

+14

¡Y podrías pensar que sería malo! Pero mira los horarios que agregué arriba ... –

+0

@glennmcdonald ¿puedes decirme cómo se pueden calcular los tiempos para cada llamada en ruby? – boddhisattva

8

<=> compara los dos operandos, devolviendo -1 si el primero es menor, 0 si son iguales y 1 si el primero es más alto. Esto significa que puede hacer -(a[1]<=>b[1]) para invertir el orden.

+1

siempre prefiero ver escrito con los elementos "a" y "b" intercambiados, en lugar de negar el resultado. Con ellos intercambiados, solo tengo que mirar su orden para ver si están al revés y saber que está invertida. Cuando el valor de '<=>' es negado, todavía tengo que mirar la comparación real para saber qué está pasando. Es un punto menor pero algo de lo que soy consciente porque puedo sentir que mi cerebro tiene que hacer el segundo control después de hacer un "¿Qué?" –

+1

@Greg: definitivamente veo por qué lo preferirías a la inversa. Soy el opuesto: a mis ojos de escaneo, 'b [1] <=> a [1]' parece hella como 'a [1] <=> b [1]' y siento la necesidad de detenerme y verificar, mientras que la negación hace es obvio de inmediato que estamos haciendo un tipo inverso. – Chuck

+0

Entiendo tu punto también. De cualquier forma, es necesario seguir detenidamente los valores que se comparan. Tal vez necesitamos un operador diferente - '> = <' para orden inverso? Nah, eso sería igual de malo. Es el constructo completo, pero prefiero '<=>' sobre un enfoque más detallado donde tendríamos que llamar a algunos nombres de métodos. –

10
h.sort {|a,b| b[1]<=>a[1]} 
+6

He votado negativamente este comentario, no porque la respuesta sea incorrecta, sino porque no explica por qué esta es la respuesta correcta. El interlocutor incluso preguntó específicamente qué significa "<=>", por lo que está claro que después de una explicación de cómo funciona todo esto. Es una buena idea ayudar de esa manera :) –

+0

PD: consulte la política de revisión de Stack Overflow en meta para obtener más información: http://meta.stackexchange.com/questions/74194/how-to-review-can-we-agree -on-a-review-policy –

5

super simple: h.sort_by { |k, v| -v }

Cuestiones relacionadas