Wäre dies der beste Weg, um einen Hash zu sortieren und ein Hash-Objekt (anstelle von Array) zurückzugeben:
h = {"a"=>1, "c"=>3, "b"=>2, "d"=>4}
# => {"a"=>1, "c"=>3, "b"=>2, "d"=>4}
Hash[h.sort]
# => {"a"=>1, "b"=>2, "c"=>3, "d"=>4}
Wäre dies der beste Weg, um einen Hash zu sortieren und ein Hash-Objekt (anstelle von Array) zurückzugeben:
h = {"a"=>1, "c"=>3, "b"=>2, "d"=>4}
# => {"a"=>1, "c"=>3, "b"=>2, "d"=>4}
Hash[h.sort]
# => {"a"=>1, "b"=>2, "c"=>3, "d"=>4}
Antworten:
In Ruby 2.1 ist es einfach:
h.sort.to_h
h.sort{|a,z|a<=>z}.to_h
(getestet 2.1.10, 2.3.3)
a
ist ein Array, nicht nur der Schlüssel). Ich habe meinen Kommentar gelöscht.
h.map(&:sort).map(&:to_h)
.
Hinweis: Ruby> = 1.9.2 hat einen auftragserhaltenden Hash: Die eingefügten Auftragsschlüssel entsprechen der Reihenfolge, in der sie aufgelistet sind. Das Folgende gilt für ältere Versionen oder für abwärtskompatiblen Code.
Es gibt kein Konzept für einen sortierten Hash. Also nein, was du tust, ist nicht richtig.
Wenn Sie möchten, dass es zur Anzeige sortiert wird, geben Sie eine Zeichenfolge zurück:
"{" + h.sort.map{|k,v| "#{k.inspect}=>#{v.inspect}"}.join(", ") + "}"
oder, wenn Sie die Schlüssel in der richtigen Reihenfolge haben möchten:
h.keys.sort
oder, wenn Sie der Reihe nach auf die Elemente zugreifen möchten:
h.sort.map do |key,value|
# keys will arrive in order to this block, with their associated value.
end
Zusammenfassend macht es jedoch keinen Sinn, über einen sortierten Hash zu sprechen. In den Dokumenten heißt es: "Die Reihenfolge, in der Sie einen Hash nach Schlüssel oder Wert durchlaufen, scheint willkürlich zu sein und liegt im Allgemeinen nicht in der Einfügereihenfolge." Das Einfügen von Schlüsseln in einer bestimmten Reihenfolge in den Hash hilft also nicht.
Ich habe immer benutzt sort_by
. Sie müssen die #sort_by
Ausgabe umschließen Hash[]
, damit sie einen Hash ausgibt, andernfalls wird ein Array von Arrays ausgegeben. Um dies zu erreichen, können Sie alternativ die #to_h
Methode für das Array von Tupeln ausführen , um sie in eine k=>v
Struktur (Hash) zu konvertieren .
hsh ={"a" => 1000, "b" => 10, "c" => 200000}
Hash[hsh.sort_by{|k,v| v}] #or hsh.sort_by{|k,v| v}.to_h
Es gibt eine ähnliche Frage in " Wie sortiere ich einen Ruby Hash nach Zahlenwert? ".
sort_by
einen Hash verwenden, wird ein Array zurückgegeben. Sie müssten es erneut als Hash zuordnen. Hash[hsh.sort_by{|k,v| v}]
hsh.sort_by(&:last).to_h => {"b"=>10, "a"=>1000, "c"=>200000}
.
to_h
nur in Ruby 2.1.0+
sort_by{|k,v| v}.to_h)
Nein, ist es nicht (Ruby 1.9.x)
require 'benchmark'
h = {"a"=>1, "c"=>3, "b"=>2, "d"=>4}
many = 100_000
Benchmark.bm do |b|
GC.start
b.report("hash sort") do
many.times do
Hash[h.sort]
end
end
GC.start
b.report("keys sort") do
many.times do
nh = {}
h.keys.sort.each do |k|
nh[k] = h[k]
end
end
end
end
user system total real
hash sort 0.400000 0.000000 0.400000 ( 0.405588)
keys sort 0.250000 0.010000 0.260000 ( 0.260303)
Bei großen Hashes wächst der Unterschied auf das 10-fache und mehr
Sie haben sich im OP die beste Antwort gegeben: Hash[h.sort]
Wenn Sie sich nach mehr Möglichkeiten sehnen, finden Sie hier eine direkte Änderung des ursprünglichen Hashs, um ihn zu sortieren:
h.keys.sort.each { |k| h[k] = h.delete k }
Sortieren Sie den Hash nach Schlüssel und geben Sie den Hash in Ruby zurück
Mit Destrukturierung und Hash # Sortierung
hash.sort { |(ak, _), (bk, _)| ak <=> bk }.to_h
Enumerable # sort_by
hash.sort_by { |k, v| k }.to_h
Hash # sort mit Standardverhalten
h = { "b" => 2, "c" => 1, "a" => 3 }
h.sort # e.g. ["a", 20] <=> ["b", 30]
hash.sort.to_h #=> { "a" => 3, "b" => 2, "c" => 1 }
Hinweis: <Ruby 2.1
array = [["key", "value"]]
hash = Hash[array]
hash #=> {"key"=>"value"}
Hinweis:> Ruby 2.1
[["key", "value"]].to_h #=> {"key"=>"value"}
v
, sollten Sie einen Unterstrich hash.sort_by { |k, _v| k }.to_h
ActiveSupport :: OrderedHash ist eine weitere Option, wenn Sie Ruby 1.9.2 nicht verwenden oder eigene Problemumgehungen durchführen möchten.
@ordered = {}
@unordered.keys.sort.each do |key|
@ordered[key] = @unordered[key]
end
Ich hatte das gleiche Problem (ich musste meine Geräte nach ihrem Namen sortieren) und löste es folgendermaßen:
<% @equipments.sort.each do |name, quantity| %>
...
<% end %>
@equipments ist ein Hash, den ich auf meinem Modell aufbaue und auf meinem Controller zurückgebe. Wenn Sie .sort aufrufen, wird der Hash nach seinem Schlüsselwert sortiert.
Mir hat die Lösung im vorherigen Beitrag gefallen.
Ich habe eine Miniklasse gemacht, sie genannt class AlphabeticalHash
. Es hat auch eine Methode namens ap
, die ein Argument, a Hash
, als Eingabe akzeptiert : ap variable
. Ähnlich wie pp ( pp variable
)
Aber es wird (versuchen und) in alphabetischer Liste (seine Schlüssel) drucken. Keine Ahnung, wenn jemand anderes dies verwenden möchte, ist es als Juwel erhältlich. Sie können es als solches installieren:gem install alphabetical_hash
Für mich ist das einfach genug. Wenn andere mehr Funktionen benötigen, lassen Sie es mich wissen, ich werde es in den Edelstein aufnehmen.
EDIT: Dank geht an Peter , der mir die Idee gegeben hat. :) :)
each
odereach_pair
iterieren darüber. Selbst dann würde ich wahrscheinlich immer noch die Schlüssel greifen, diese sortieren und dann darüber iterieren und die Werte nach Bedarf abrufen. Dadurch wird sichergestellt, dass sich der Code auf älteren Rubinen korrekt verhält.