2010-03-29 9 views
127

Ho un hash del contatore che sto cercando di ordinare per numero. Il problema che sto incontrando è che la funzione Hash.sort predefinita ordina numeri come stringhe piuttosto che in base alla dimensione del numero.Come ordinare un hash di Ruby in base al valore numerico?

cioè Hash Data:

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

esecuzione di questo codice:

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

restituisce un array ordinato:

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

Anche se 745 è un numero maggiore di 9, 9 apparirà prima nella lista. Quando provo a mostrare chi ha il primo conteggio, questo mi rende la vita difficile. :)

Qualche idea su come ordinare un hash (o un array pari) per la dimensione del valore numerico?

Apprezzo qualsiasi aiuto.

+0

quale versione rubino usi? il tuo risultato sort è molto strano – fl00r

risposta

225

Nessuna idea di come avete ottenuto i risultati, dal momento che non sarebbe ordina per valore di stringa ... Si dovrebbe invertire a1 e a2 nel tuo esempio

Il modo migliore in ogni caso (come per 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 avete bisogno di un hash di conseguenza, è possibile utilizzare to_h (in Ruby 2.0+)

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

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

+1

infatti ... Risposta udpated :-) –

+0

Il mio numero stava ritornando come una stringa, che lo ha risolto .. Avevo a2 e a1 in quell'ordine perché volevo che i risultati fossero ordinati decrescenti .. grazie per il tuo feedback . –

8

non è questo il comportamento 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 numeri vengano convertiti in stringhe? C'è altro codice che non stai postando?

+0

Ah il tuo diritto sembra che il risultato nel mio codice lo stia restituendo come una stringa. Tipi di dati Pesky. :) A volte sono troppo vicino al problema. Grazie. –

+1

Sì. Ogni tanto sento che qualcuno si riferisce a Ruby come "non tipizzato". Oh, no, è sicuramente digitato. Non è solo tipizzato staticamente. :) –

12

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

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

Convertito in archi lungo la strada oppure no, questo farà il lavoro.

70

Dal momento che il valore è l'ultima voce, si può fare:

metrics.sort_by(&:last) 
+0

Risposta straordinaria con grande semplicità! –

+4

Questo è fantastico! qualsiasi referenza per la pre-definizione di '&: last'? –

+0

'sort_by (&: last)' è in pratica una scorciatoia per 'sort_by {| x | x.last} 'https://stackoverflow.com/questions/1217088/what-does-mapname-mean-in-ruby –

Problemi correlati