¿Cómo ordenar un Ruby Hash por valor numérico?


154

Tengo un contador hash que estoy tratando de ordenar por conteo. El problema con el que me encuentro es que la función Hash.sort predeterminada ordena los números como cadenas en lugar de por tamaño de número.

es decir, Hash dado:

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

Ejecutando este código:

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

devolverá una matriz ordenada:

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

Aunque 745 es un número mayor que 9, 9 aparecerá primero en la lista. Cuando trato de mostrar quién tiene la cuenta más alta, esto me dificulta la vida. :)

¿Alguna idea sobre cómo ordenar un hash (o incluso una matriz) por tamaño de valor numérico?

Agradezco cualquier ayuda.


¿Qué versión de rubí usas? el resultado de su clasificación es muy extraño
fl00r

Respuestas:


268

No tengo idea de cómo obtuviste tus resultados, ya que no se ordenaría por valor de cadena ... Debes invertir a1y a2en tu ejemplo

La 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 usar to_h(en Ruby 2.0+)

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

84
o simplementesort_by{|k,v| v}
Mladen Jablanović

Mi número estaba regresando como una cadena, eso lo solucionó ... Tenía a2 y a1 en ese orden porque quería que los resultados ordenaran los descendientes ... aunque gracias por sus comentarios.
Dustin M.

es por eso que amo a Ruby ... tal problema es dolor de cabeza en otros idiomas. tan simple
Hady Elsahar

18
@Elchin: puedes usarmetrics.sort_by{ |k, v| v }.reverse.to_h
Marc-André Lafortune

44
En realidad, incluso más simple como: hash.sort_by (&: last) con la misma advertencia sobre cómo obtener una matriz de pares frente a un Hash.
Gerry Gleason


14

Ya respondí pero aún así. Cambia tu código a:

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

Convertido a cadenas en el camino o no, esto hará el trabajo.


9

Ese no es el comportamiento que 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 sus números se conviertan en cadenas? ¿Hay más código que no estás publicando?


Ahh a la derecha, parece que el resultado en mi código lo devolvió como una cadena. Tipos de datos molestos. :) A veces estoy demasiado cerca del problema. Gracias.
Dustin M.

1
Sip. Ocasionalmente escucho a alguien referirse a Ruby como "sin tipo". Oh, no, definitivamente está escrito. Simplemente no está estáticamente escrito. :)
Jacob Mattison
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.