Jak posortować Ruby Hash według wartości liczbowej?


154

Mam licznik hash, który próbuję posortować według liczby. Problem, z którym się spotykam, polega na tym, że domyślna funkcja Hash.sort sortuje liczby jako ciągi znaków, a nie według rozmiaru liczb.

tj. Given Hash:

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

Uruchamianie tego kodu:

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

zwróci posortowaną tablicę:

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

Mimo że 745 to liczba większa niż 9, 9 pojawi się jako pierwsze na liście. Kiedy próbuję pokazać, kto jest najważniejszy, utrudnia mi to życie. :)

Jakieś pomysły na sortowanie skrótu (lub nawet tablicy) według rozmiaru wartości liczbowej?

Doceniam każdą pomoc.


jakiej wersji ruby ​​używasz? Twój wynik sortowania jest bardzo dziwny
fl00r

Odpowiedzi:


268

Nie mam pojęcia, jak otrzymałeś wyniki, ponieważ nie posortowałoby to według wartości ciągu ... Powinieneś odwrócić a1i a2w swoim przykładzie

W każdym przypadku najlepszym sposobem (według Mladena) jest:

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

Jeśli w rezultacie potrzebujesz skrótu, możesz użyć to_h(w Ruby 2.0+)

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

84
lub po prostusort_by{|k,v| v}
Mladen Jablanović

Moja liczba zwracała się jako ciąg znaków, który to naprawił. Miałem a2 i a1 w tej kolejności, ponieważ chciałem, aby wyniki były sortowane w porządku malejącym ... dzięki za Twoją opinię.
Dustin M.

dlatego kocham Ruby ... taki problem to ból głowy w innych językach. so simple
Hady Elsahar

18
@Elchin: możesz użyćmetrics.sort_by{ |k, v| v }.reverse.to_h
Marc-André Lafortune

4
Właściwie nawet prostsze, jak: hash.sort_by (&: last) z tym samym zastrzeżeniem dotyczącym uzyskiwania tablicy par kontra Hash.
Gerry Gleason


14

Już odpowiedziałem, ale nadal. Zmień kod na:

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

Konwertowane na ciągi po drodze lub nie, to wykona zadanie.


9

To nie jest zachowanie, które widzę:

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

Czy to możliwe, że gdzieś wzdłuż linii twoje liczby są konwertowane na łańcuchy? Czy jest więcej kodu, którego nie publikujesz?


Ach, masz rację, wygląda na to, że wynik w moim kodzie zwracał go jako ciąg. Brzydkie typy danych. :) Czasami jestem po prostu zbyt blisko problemu. Dzięki.
Dustin M.

1
Tak. Czasami słyszę, że ktoś odnosi się do Rubiego jako „bez typu”. O nie, to zdecydowanie wpisane. Po prostu nie jest wpisany statycznie. :)
Jacob Mattison,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.