Come ordinare un Ruby Hash in base al valore numerico?


154

Ho un contatore di hash che sto cercando di ordinare in base al conteggio. Il problema in cui mi imbatto è che la funzione Hash.sort predefinita ordina i numeri come stringhe anziché per dimensione numerica.

vale a dire Hash dato:

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

In esecuzione questo codice:

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

restituirà un array ordinato:

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

Anche se 745 è un numero maggiore di 9, 9 apparirà per primo nell'elenco. Quando provo a mostrare chi ha il massimo dei voti, questo mi rende la vita difficile. :)

Qualche idea su come ordinare un hash (o un array pari) in base alla dimensione del valore numerico?

Apprezzo qualsiasi aiuto.


che versione di ruby ​​usi? il risultato del tuo ordinamento è molto strano
fl00r

Risposte:


268

Non ho idea di come hai ottenuto i risultati, dal momento che non si ordina per valore di stringa ... Dovresti invertire a1e a2nel tuo esempio

Il modo migliore in ogni caso (secondo Mladen) è:

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]]

Se hai bisogno di un hash di conseguenza, puoi usare to_h(in Ruby 2.0+)

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

84
o semplicementesort_by{|k,v| v}
Mladen Jablanović il

Il mio numero stava tornando come una stringa, che lo risolveva. Avevo a2 e a1 in quell'ordine perché volevo che i risultati fossero in ordine decrescente .. grazie comunque per il tuo feedback.
Dustin M.

ecco perché amo Ruby ... un tale problema è il dolore alla testa in altre lingue. così semplice
Hady Elsahar il

18
@Elchin: puoi usaremetrics.sort_by{ |k, v| v }.reverse.to_h
Marc-André Lafortune il

4
In realtà anche più semplice di: hash.sort_by (&: last) con lo stesso avvertimento su come ottenere una matrice di coppie contro un hash.
Gerry Gleason,


14

Già risposto ma ancora. Cambia il tuo codice in:

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

Convertito in stringhe lungo la strada o no, questo farà il lavoro.


9

Non è questo il comportamento che sto vedendo:

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]]

È possibile che da qualche parte lungo la linea i tuoi numeri vengano convertiti in stringhe? C'è altro codice che non pubblichi?


Ah, hai ragione, sembra che il risultato nel mio codice sia stato restituirlo come stringa. Tipi di dati fastidiosi. :) A volte sono troppo vicino al problema. Grazie.
Dustin M.

1
Sì. Ogni tanto sento qualcuno che si riferisce a Ruby come "non tipizzato". Oh, no, è sicuramente scritto. Non è solo staticamente digitato. :)
Jacob Mattison,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.