Wie sortiere ich einen Ruby Hash nach Zahlenwert?


154

Ich habe einen Zähler-Hash, den ich nach Zählung sortieren möchte. Das Problem, auf das ich stoße, ist, dass die Standardfunktion Hash.sort Zahlen eher nach Zeichenfolgen als nach Zahlengröße sortiert.

dh gegebener Hash:

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

Ausführen dieses Codes:

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

gibt ein sortiertes Array zurück:

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

Obwohl 745 eine größere Zahl als 9 ist, wird 9 zuerst in der Liste angezeigt. Wenn ich versuche zu zeigen, wer die höchste Punktzahl hat, macht mir das das Leben schwer. :) :)

Irgendwelche Ideen, wie man einen Hash (oder sogar ein Array) nach der Größe des Zahlenwerts sortiert?

Ich freue mich über jede Hilfe.


Welche Ruby-Version benutzt du? Ihr Sortierergebnis ist sehr seltsam
fl00r

Antworten:


268

Keine Ahnung , wie Sie Ihre Ergebnisse erhalten, da es von String - Wert nicht sortieren würde ... Sie umkehren sollen a1und a2in Ihrem Beispiel

Der beste Weg ist auf jeden Fall (nach 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]]

Wenn Sie als Ergebnis einen Hash benötigen, können Sie ihn verwenden to_h(in Ruby 2.0+).

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

84
oder einfachsort_by{|k,v| v}
Mladen Jablanović

Meine Nummer kehrte als Zeichenfolge zurück, die das Problem behoben hat. Ich hatte a2 und a1 in dieser Reihenfolge, weil ich wollte, dass die Ergebnisse absteigend sortiert werden. Vielen Dank für Ihr Feedback.
Dustin M.

Deshalb liebe ich Ruby ... ein solches Problem ist Kopfschmerzen in anderen Sprachen. so einfach
Hady Elsahar

18
@ Elchin: Sie können verwendenmetrics.sort_by{ |k, v| v }.reverse.to_h
Marc-André Lafortune

4
Eigentlich noch einfacher als: hash.sort_by (&: last) mit der gleichen Einschränkung, ein Array von Paaren gegen einen Hash zu erhalten.
Gerry Gleason


14

Bereits beantwortet, aber immer noch. Ändern Sie Ihren Code in:

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

Auf dem Weg in Strings konvertiert oder nicht, wird dies den Job erledigen.


9

Das ist nicht das Verhalten, das ich sehe:

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

Ist es möglich, dass Ihre Zahlen irgendwo entlang der Linie in Zeichenfolgen umgewandelt werden? Gibt es mehr Code, den Sie nicht veröffentlichen?


Ahh, du hast Recht, es sieht so aus, als hätte das Ergebnis in meinem Code es als Zeichenfolge zurückgegeben. Lästige Datentypen. :) Manchmal bin ich dem Problem einfach zu nahe. Vielen Dank.
Dustin M.

1
Jep. Gelegentlich höre ich jemanden, der Ruby als "untypisiert" bezeichnet. Oh nein, es ist definitiv getippt. Es ist einfach nicht statisch typisiert. :)
Jacob Mattison
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.