Comment trier un Ruby Hash par valeur numérique?


154

J'ai un hachage de compteur que j'essaie de trier par décompte. Le problème que je rencontre est que la fonction par défaut Hash.sort trie les nombres comme des chaînes plutôt que par taille de nombre.

ie Donné Hash:

metrics = {"sitea.com" => 745, "siteb.com" => 9, "sitec.com" => 10 }

Exécution de ce code:

metrics.sort {|a1,a2| a2[1]<=>a1[1]}

renverra un tableau trié:

[ 'siteb.com', 9, 'sitea.com', 745, 'sitec.com', 10]

Même si 745 est un nombre supérieur à 9, 9 apparaîtra en premier dans la liste. En essayant de montrer qui a le plus grand nombre, cela me rend la vie difficile. :)

Des idées sur la façon de trier un hachage (ou même un tableau) par taille de valeur numérique?

J'apprécie toute aide.


quelle version ruby ​​utilisez-vous? votre résultat de tri est très étrange
fl00r

Réponses:


268

Aucune idée de la façon dont vous avez obtenu vos résultats, car il ne trierait pas par valeur de chaîne ... Vous devriez inverser a1et a2dans votre exemple

Le meilleur moyen dans tous les cas (selon Mladen) est:

metrics = {"sitea.com" => 745, "siteb.com" => 9, "sitec.com" => 10 }
metrics.sort_by {|_key, value| value}
  # ==> [["siteb.com", 9], ["sitec.com", 10], ["sitea.com", 745]]

Si vous avez besoin d'un hachage, vous pouvez utiliser to_h(dans Ruby 2.0+)

metrics.sort_by {|_key, value| value}.to_h
  # ==> {"siteb.com" => 9, "sitec.com" => 10, "sitea.com", 745}

84
ou simplementsort_by{|k,v| v}
Mladen Jablanović

Mon numéro revenait sous forme de chaîne, cela a corrigé le problème .. J'avais a2 et a1 dans cet ordre parce que je voulais que les résultats soient triés par ordre décroissant .. merci pour vos commentaires.
Dustin M.

c'est pourquoi j'aime Ruby ... un tel problème est la douleur dans la tête dans d'autres langues. so simple
Hady Elsahar

18
@Elchin: vous pouvez utilisermetrics.sort_by{ |k, v| v }.reverse.to_h
Marc-André Lafortune

4
En fait encore plus simple que: hash.sort_by (&: last) avec la même mise en garde concernant l'obtention d'un tableau de paires par rapport à un hachage.
Gerry Gleason


14

Déjà répondu mais toujours. Changez votre code en:

metrics.sort {|a1,a2| a2[1].to_i <=> a1[1].to_i }

Converti en chaînes en cours de route ou non, cela fera l'affaire.


9

Ce n'est pas le comportement que je vois:

irb(main):001:0> metrics = {"sitea.com" => 745, "siteb.com" => 9, "sitec.com" =>
 10 }
=> {"siteb.com"=>9, "sitec.com"=>10, "sitea.com"=>745}
irb(main):002:0> metrics.sort {|a1,a2| a2[1]<=>a1[1]}
=> [["sitea.com", 745], ["sitec.com", 10], ["siteb.com", 9]]

Est-il possible que quelque part le long de la ligne, vos nombres soient convertis en chaînes? Y a-t-il plus de code que vous ne publiez pas?


Ahh votre droite, il semble que le résultat dans mon code le renvoie sous forme de chaîne. Types de données inquiétants. :) Parfois, je suis trop près du problème. Merci.
Dustin M.

1
Ouaip. Parfois, j'entends quelqu'un qualifier Ruby de "non typé". Oh, non, c'est définitivement tapé. Ce n'est tout simplement pas typé statiquement. :)
Jacob Mattison
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.