2010-03-29 18 views
127

Tengo un contador de hash que intento ordenar por conteo. El problema al que me estoy enfrentando es que la función predeterminada Hash.sort ordena números como cadenas en lugar de por tamaño de número.¿Cómo ordenar un Ruby Hash por valor numérico?

es decir Hash Dado:

metrics = {"sitea.com" => 745, "siteb.com" => 9, "sitec.com" => 10 } 

La ejecución de este código:

metrics.sort {|a1,a2| a2[1]<=>a1[1]} 

devolverá una matriz ordenada:

[ 'siteb.com', 9, 'sitea.com', 745, 'sitec.com', 10] 

A pesar de que 745 es un número mayor que 9, 9 aparecerá primero en la lista. Cuando trato de mostrar quién tiene el conteo más alto, esto me está haciendo la vida difícil. :)

¿Alguna idea sobre cómo ordenar un hash (o incluso un array) por tamaño de valor?

Agradezco cualquier ayuda.

+0

qué versión rubí utiliza? el resultado de su clasificación es muy extraño – fl00r

Respuesta

225

Ni idea de cómo ha llegado a sus resultados, ya que no ordenar por valor de cadena ... Usted debe invertir a1 y a2 en su ejemplo

mejor manera en cualquier caso (según Mladen) es:

metrics = {"sitea.com" => 745, "siteb.com" => 9, "sitec.com" => 10 } 
metrics.sort_by {|_key, value| value} 
    # ==> [["siteb.com", 9], ["sitec.com", 10], ["sitea.com", 745]] 

Si necesita un hash como resultado, puede utilizar to_h (en Ruby 2.0+)

metrics.sort_by {|_key, value| value}.to_h 
    # ==> {"siteb.com" => 9, "sitec.com" => 10, "sitea.com", 745} 
+79

o simplemente 'sort_by {| k, v | v} ' –

+1

de hecho ... Respuesta udpated :-) –

+0

Mi número volvía como una cadena, lo arregló ... Tenía a2 y a1 en ese orden porque quería que los resultados se ordenaran decentemente ... gracias por sus comentarios . –

8

Ese no es el comportamiento Estoy viendo:

irb(main):001:0> metrics = {"sitea.com" => 745, "siteb.com" => 9, "sitec.com" => 
10 } 
=> {"siteb.com"=>9, "sitec.com"=>10, "sitea.com"=>745} 
irb(main):002:0> metrics.sort {|a1,a2| a2[1]<=>a1[1]} 
=> [["sitea.com", 745], ["sitec.com", 10], ["siteb.com", 9]] 

¿Es posible que en algún lugar a lo largo de la línea de sus números se convierten en cadenas? ¿Hay más código que no estás publicando?

+0

Ahh, su derecha, parece que el resultado en mi código fue devolverlo como una cadena. Tipos de datos molestos :) A veces estoy demasiado cerca del problema. Gracias. –

+1

Sí. De vez en cuando, escucho a alguien referirse a Ruby como "sin tipo". Oh, no, definitivamente está escrito. Simplemente no está tipado estáticamente. :) –

12

Ya se ha respondido, pero aún así. Cambiar el código para:

metrics.sort {|a1,a2| a2[1].to_i <=> a1[1].to_i } 

convierten en cadenas en el camino o no, esto va a hacer el trabajo.

70

Desde valor es la última entrada, puede hacerlo:

metrics.sort_by(&:last) 
+0

¡Respuesta impresionante con gran simplicidad! –

+4

¡Esto es asombroso! cualquier referencia para la pre-definición de '&: last'? –

+0

'sort_by (&: last)' es una forma abreviada de 'sort_by {| x | x.last} 'https://stackoverflow.com/questions/1217088/what-does-mapname-mean-in-ruby –

Cuestiones relacionadas