Serait-ce le meilleur moyen de trier un hachage et de renvoyer un objet Hash (au lieu de Array):
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}
En Ruby 2.1, c'est simple:
h.sort.to_h
Remarque: Ruby> = 1.9.2 a un hachage préservant l'ordre: les clés d'ordre insérées correspondent à l'ordre dans lequel elles sont énumérées. Ce qui suit s’applique aux anciennes versions ou aux codes rétrocompatibles.
Il n'y a pas de concept de hachage trié. Donc non, ce que vous faites n'est pas juste.
Si vous voulez qu'il soit trié pour l'affichage, retournez une chaîne:
"{" + h.sort.map{|k,v| "#{k.inspect}=>#{v.inspect}"}.join(", ") + "}"
ou, si vous voulez les clés dans l’ordre:
h.keys.sort
ou, si vous souhaitez accéder aux éléments dans l'ordre:
h.sort.map do |key,value|
# keys will arrive in order to this block, with their associated value.
end
mais en résumé, cela n'a aucun sens de parler d'un hachage trié. Dans docs , "L’ordre dans lequel vous parcourez un hachage avec une clé ou une valeur peut sembler arbitraire et ne sera généralement pas dans l’ordre d’insertion." Donc, insérer des clés dans un ordre spécifique dans le hachage ne vous aidera pas.
J'ai toujours utilisé sort_by
. Vous devez encapsuler la sortie #sort_by
avec Hash[]
pour lui faire afficher un hachage, sinon elle génère un tableau de tableaux. Pour ce faire, vous pouvez également exécuter la méthode #to_h
sur le tableau de tuples afin de les convertir en une structure k=>v
(hachage).
hsh ={"a" => 1000, "b" => 10, "c" => 200000}
Hash[hsh.sort_by{|k,v| v}] #or hsh.sort_by{|k,v| v}.to_h
Il existe une question similaire dans " Comment trier un Ruby Hash par valeur numérique? ".
Non, ce n'est pas (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)
Pour les grands hachages, la différence passera à 10x et plus
Vous vous êtes donné la meilleure réponse dans l'OP: Hash[h.sort]
Si vous avez envie de plus de possibilités, voici une modification en place du hachage d'origine pour le trier:
h.keys.sort.each { |k| h[k] = h.delete k }
ActiveSupport :: OrderedHash est une autre option si vous ne souhaitez pas utiliser Ruby 1.9.2 ou lancer vos propres solutions de contournement.
Trier le hachage par clé, retourner le hachage en Ruby
Avec déstructuration et tri par hachage
hash.sort { |(ak, _), (bk, _)| ak <=> bk }.to_h
Enumérable # sort_by
hash.sort_by { |k, v| k }.to_h
Hash # sort avec un comportement par défaut
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 }
Remarque: <Ruby 2.1
array = [["key", "value"]]
hash = Hash[array]
hash #=> {"key"=>"value"}
Remarque:> Ruby 2.1
[["key", "value"]].to_h #=> {"key"=>"value"}
J'ai eu le même problème (je devais trier mes équipements par leur nom) et j'ai résolu comme ça:
<% @equipments.sort.each do |name, quantity| %>
...
<% end %>
@equipments est un hash que je construis sur mon modèle et que je retourne sur mon contrôleur. Si vous appelez .sort, le hachage sera trié en fonction de sa valeur clé.
@ordered = {}
@unordered.keys.sort.each do |key|
@ordered[key] = @unordered[key]
end