Serait-ce la meilleure façon de trier un hachage et de renvoyer un objet Hash (au lieu d'un tableau):
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}
Serait-ce la meilleure façon de trier un hachage et de renvoyer un objet Hash (au lieu d'un tableau):
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}
Réponses:
Dans Ruby 2.1, c'est simple:
h.sort.to_h
h.sort{|a,z|a<=>z}.to_h
(testé 2.1.10, 2.3.3)
a
c'est un tableau, pas seulement la clé). J'ai supprimé mon commentaire.
h.map(&:sort).map(&:to_h)
.
Remarque: Ruby> = 1.9.2 a un hachage préservant l'ordre: les clés de commande insérées seront l'ordre dans lequel elles sont énumérées. Ce qui suit s'applique aux anciennes versions ou au code rétrocompatible.
Il n'y a pas de concept de hachage trié. Alors non, ce que tu fais n'est pas bien.
Si vous souhaitez le trier pour l'affichage, renvoyez 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é. D'après les documents , "L'ordre dans lequel vous parcourez un hachage par clé ou par valeur peut sembler arbitraire et ne sera généralement pas dans l'ordre d'insertion." Ainsi, l'insertion de clés dans un ordre spécifique dans le hachage n'aidera pas.
Je l'ai toujours utilisé sort_by
. Vous devez envelopper la #sort_by
sortie avec Hash[]
pour en faire une sortie de hachage, sinon elle génère un tableau de tableaux. Alternativement, pour ce faire, vous pouvez exécuter la #to_h
méthode sur le tableau de tuples pour les convertir en une k=>v
structure (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 y a une question similaire dans " Comment trier un hachage Ruby par valeur numérique? ".
sort_by
d'un hachage renvoie un tableau. Vous devrez à nouveau le mapper comme un hachage. Hash[hsh.sort_by{|k,v| v}]
hsh.sort_by(&:last).to_h => {"b"=>10, "a"=>1000, "c"=>200000}
.
to_h
n'est pris en charge que dans Ruby 2.1.0+
sort_by{|k,v| v}.to_h)
Non, ce n'est pas le cas (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 gros hachages, la différence augmentera jusqu'à 10 fois et plus
Vous avez donné la meilleure réponse à vous-même 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 }
Trier le hachage par clé , retourner le hachage en Ruby
Avec déstructuration et tri Hash #
hash.sort { |(ak, _), (bk, _)| ak <=> bk }.to_h
Enumerable # sort_by
hash.sort_by { |k, v| k }.to_h
Tri Hash # avec 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"}
v
vous devez préfixer un trait de soulignementhash.sort_by { |k, _v| k }.to_h
ActiveSupport :: OrderedHash est une autre option si vous ne voulez pas utiliser ruby 1.9.2 ou lancer vos propres solutions de contournement.
@ordered = {}
@unordered.keys.sort.each do |key|
@ordered[key] = @unordered[key]
end
J'ai eu le même problème (j'ai dû trier mes équipements par leur nom) et j'ai résolu comme ceci:
<% @equipments.sort.each do |name, quantity| %>
...
<% end %>
@equipments est un hachage que je construis sur mon modèle et que je retourne sur mon contrôleur. Si vous appelez .sort, il triera le hachage en fonction de sa valeur clé.
J'ai aimé la solution dans le post précédent.
J'ai fait un mini-cours, je l'ai appelé class AlphabeticalHash
. Il a également une méthode appelée ap
, qui accepte un argument, une Hash
, en entrée: ap variable
. Similaire à pp ( pp variable
)
Mais il va (essayer et) imprimer dans la liste alphabétique (ses clés). Ne sais pas si quelqu'un d'autre veut l'utiliser, il est disponible en tant que gemme, vous pouvez l'installer comme tel:gem install alphabetical_hash
Pour moi, c'est assez simple. Si d'autres ont besoin de plus de fonctionnalités, faites-le moi savoir, je les inclurai dans la gemme.
EDIT: Le mérite revient à Peter , qui m'a donné l'idée. :)
each
ou queeach_pair
vous le répétiez. Même alors, j'attraperais probablement les clés, les trierais, puis les répéterais en saisissant les valeurs selon les besoins. Cela garantit que le code se comportera correctement sur les anciens Rubis.