Je ne suis pas sûr qu'il y ait beaucoup d'avantages à trier un hachage, à moins que vous ne l'utilisiez eachou que each_pairvous 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.
The Tin Man
Est également logique dans ruby 1.9. J'avais une collection de rendez-vous regroupés par dates (sous forme de clés) provenant de db et j'ai trié manuellement par rubis. Par exemple. {"2012-09-22": [...], "2012-09-30": [...], "2012-10-12": [...]}
Adit Saxena
Oui, je trouve que votre processus Hash [h.sort] est plus efficace que le tri des clés, puis que vous accédez à nouveau au hachage via les clés triées.
@zachaysan mais ça marche: h.sort{|a,z|a<=>z}.to_h(testé 2.1.10, 2.3.3)
whitehat101
@ whitehat101 Vous avez raison. J'ai eu un bug ( ac'est un tableau, pas seulement la clé). J'ai supprimé mon commentaire.
zachaysan
Juste au cas où quelqu'un d' autre est à la recherche d'un moyen de trier un tableau de hash, cela fera l'affaire (où h est le tableau): h.map(&:sort).map(&:to_h).
JM Janzen
82
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:
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.
"À partir de la version 1.9.2, l'ordre d'insertion de hachage sera conservé.", Et c'est adorable.
The Tin Man
2
Concernant mon premier commentaire (se sentir drôle): Par exemple, s'appuyer sur l'ordre de hachage se briserait en silence et de manière imprévisible pour les versions Ruby antérieures à 1.9.2.
Jo Liss
5
Comment cette réponse a-t-elle obtenu environ 20 + 1 sans répondre à aucune des deux parties de la question OP? "1) Serait-ce (exemple OP) le meilleur moyen de trier un hachage, 2) et de renvoyer un objet Hash"? Je n'envie pas les +1 :) c'est juste après cette lecture de la réponse que je reste avec les questions originales. Aussi, si le fait est qu'il n'y a pas de hachage trié, regardez les commentaires pour la réponse
choisie
64
Je l'ai toujours utilisé sort_by. Vous devez envelopper la #sort_bysortie 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_hméthode sur le tableau de tuples pour les convertir en une k=>vstructure (hachage).
l'utilisation sort_byd'un hachage renvoie un tableau. Vous devrez à nouveau le mapper comme un hachage. Hash[hsh.sort_by{|k,v| v}]
stevenspiel
1
oui, la classe d'énumérateur interprète les hachages comme des tableaux, je pense
boulder_ruby
3
, Est en quelque sorte droit sur les valeurs: hsh.sort_by(&:last).to_h => {"b"=>10, "a"=>1000, "c"=>200000}.
Cary Swoveland
1
Notez que l'appel to_hn'est pris en charge que dans Ruby 2.1.0+
Phrogz
1
il y a une faute de frappe dans le commentaire, correction:sort_by{|k,v| v}.to_h)
gigue le
13
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 doHash[h.sort]endend
GC.start
b.report("keys sort")do
many.times do
nh ={}
h.keys.sort.each do|k|
nh[k]= h[k]endendendend
user system total real
hash sort 0.4000000.0000000.400000(0.405588)
keys sort 0.2500000.0100000.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:
J'ai corrigé le lien pour pointer vers Google au cas où un historien voudrait rechercher comment cela aurait pu être fait dans le passé. Mais quiconque vient à ce sujet maintenant devrait utiliser une version plus récente de Ruby.
@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 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.Réponses:
Dans Ruby 2.1, c'est simple:
la source
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:
ou, si vous voulez les clés dans l'ordre:
ou, si vous souhaitez accéder aux éléments dans l'ordre:
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.
la source
Je l'ai toujours utilisé
sort_by
. Vous devez envelopper la#sort_by
sortie avecHash[]
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 unek=>v
structure (hachage).Il y a une question similaire dans " Comment trier un hachage Ruby par valeur numérique? ".
la source
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)
Pour les gros hachages, la différence augmentera jusqu'à 10 fois et plus
la source
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:la source
Avec déstructuration et tri Hash #
Enumerable # sort_by
Tri Hash # avec comportement par défaut
Remarque: <Ruby 2.1
Remarque:> Ruby 2.1
la source
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.
la source
la source
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 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é.
la source
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éeap
, qui accepte un argument, uneHash
, 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. :)
la source