/ / Trier les éléments d'un hachage imbriqué en fonction de leurs valeurs - ruby, tri

Trier les éléments d'un hachage imbriqué en fonction de leurs valeurs - ruby, tri

Je reçois un hachage imbriqué qui doit être trié selon ses valeurs. Par exemple:

@foo = {"a"=>{"z"=>5, "y"=>3, "x"=>88}, "b"=>{"a"=>2, "d"=>-5}}

Lors de l'exécution de ce qui suit:

@foo["a"].sort{|a,b| a[1]<=>b[1]}

Je reçois:

[["y", 3], ["z", 5], ["x", 88]]

C’est génial, c’est exactement ce que je veux. Le problème est que je ne vais pas toujours savoir quelles sont les clés qui me sont envoyées, alors j’ai besoin d’une sorte de boucle. J'ai essayé de faire ce qui suit:

@foo.each do |e|
e.sort{|a,b| a[1]<=>b[1]}
end

Cela me semble logique puisque si j'appelle manuellement @ foo.first [0], je reçois

"a"

et @ foo.first [1] renvoie

{"z"=>5, "y"=>3, "x"=>8}

mais pour une raison quelconque, ce n'est pas "trier correctement(par exemple du tout). Je suppose que cela est dû au fait que chaque appelle le tri sur l’ensemble de l’objet de hachage plutôt que sur les valeurs de "a". Comment accéder aux valeurs du hachage imbriqué sans savoir quelle est sa clé?

Réponses:

6 pour la réponse № 1

Vous voudrez peut-être faire une boucle sur le hachage comme ceci:

@ foo.each do | key, value | @foo [key] = value.sort {| a, b | a [1] <=> b [1]} fin

4 pour la réponse № 2
@foo = {"a"=>{"z"=>5, "y"=>3, "x"=>88}, "b"=>{"a"=>2, "d"=>-5}}
@bar = Hash[ @foo.map{ |key,values| [ key, values.sort_by(&:last) ] } ]

Ou, via un chemin moins compliqué:

@bar = {}
@foo.each do |key,values|
@bar[key] = values.sort_by{ |key,value| value }
end

Dans les deux cas @bar se révèle être:

p @bar
#=> {
#=>   "a"=>[["y", 3], ["z", 5], ["x", 88]],
#=>   "b"=>[["d", -5], ["a", 2]]
#=> }

1 pour la réponse № 3

Mon collègue a proposé une solution légèrement plus flexible qui triera récursivement un tableau de toutes les profondeurs:

def deep_sort_by(&block)
Hash[self.map do |key, value|
[if key.respond_to? :deep_sort_by
key.deep_sort_by(&block)
else
key
end,

if value.respond_to? :deep_sort_by
value.deep_sort_by(&block)
else
value
end]

end.sort_by(&block)]
end

Vous pouvez l'injecter dans tous les hachages et ensuite l'appeler comme suit:

myMap.deep_sort_by { |obj| obj }

Le code serait similaire pour un tableau. nous publié comme un joyau pour les autres à utiliser, voir article de blog pour plus de détails.

Disclaimer: Je travaille pour cette entreprise.


0 pour la réponse № 4

dans votre exemple e est un tableau temporaire contenant une paire [clé, valeur]. Dans ce cas, la clé de caractère et le hachage imbriqué. Alors e.sort{|a,b|...} va essayer de comparer le caractère au hachage, et échoue avec une erreur d'exécution. Je pense que tu voulais probablement taper e[1].sort{...}. Mais même cela ne fonctionnera pas correctement, car vous ne stockez le hachage trié nulle part: @foo.each renvoie l'original @foo et le laisse inchangé.

La meilleure solution est celle proposée par @Pan Thomakos:

@foo.each do |key, value|
@foo[key] = value.sort{ |a,b| a[1]<=>b[1] }
end