2008-12-12 7 views
4

J'ai un Hash comme celui-ciComment trier pas simple hachage (hachage de hachages)

{ 55 => {:value=>61, :rating=>-147}, 
    89 => {:value=>72, :rating=>-175}, 
    78 => {:value=>64, :rating=>-155}, 
    84 => {:value=>90, :rating=>-220}, 
    95 => {:value=>39, :rating=>-92}, 
    46 => {:value=>97, :rating=>-237}, 
    52 => {:value=>73, :rating=>-177}, 
    64 => {:value=>69, :rating=>-167}, 
    86 => {:value=>68, :rating=>-165}, 
    53 => {:value=>20, :rating=>-45} 
} 

Comment puis-je trier par : Evaluation? Ou peut-être que je devrais utiliser une structure différente?

+1

probablement intéressant de noter le langage de programmation dans le titre. – danieltalsky

Répondre

5

je changerais la structure de données à un tableau de hachages:

my_array = 
[ 
    {:id => 78, :value=>64, :rating=>-155}, 
    {:id => 84, :value=>90, :rating=>-220}, 
    {:id => 95, :value=>39, :rating=>-92} 
] 

Vous pouvez trier ce type de structure facilement avec

my_array.sort_by { |record| record[:rating] } 

Pour obtenir la fonctionnalité de hachage de récupérer un enregistrement par ID, vous pouvez définir une nouvelle méthode sur my_array:

def my_array.find_by_id(id) 
    self.find { |hash| hash[:id] == id } 
end 

donc après que vous pouvez faire

my_array.find_by_id(id) 

au lieu de

my_hash[id] 
+0

Je ne sais pas si ce commentaire sera répondu après 4 ans .... La raison pour laquelle j'utilise un hachage est d'utiliser une clé à laquelle je peux accéder directement et incrémenter le valeurs, par exemple, h [436246]. Après avoir rempli le hachage, dois-je le convertir en tableau – nilanjan

+0

Vous pouvez le reconvertir en Hash avec 'Hash [my_array.sort_by {| record | record [: rating]}] '. Si vous utilisez Ruby 1.9.x ou plus tard car il maintient l'ordre de tri du hachage en interne. –

+0

Merci cela a craqué pour moi. Une structure de données beaucoup plus agréable pour travailler avec! ..... même si ce post est si vieux, j'ai appris quelque chose :) –

5

Hashes à Ruby ne peuvent pas être triés (au moins pas avant 1.9)

Cela signifie que par une boucle Hash donnera pas nécessairement les informations dans l'ordre pour vous. Cependant, il est trivial de boucle à travers les données HASHED dans un ordre particulier en le convertissant en un tableau d'abord, et en fait d'appeler les méthodes de tri sur une table de hachage se convertir en un tableau pour vous:

>> { :a => 4, :b => 12, :c => 3, :d => 8 }.sort_by { |key, value| value } 
=> [[:c, 3], [:a, 4], [:d, 8], [:b, 12]] 

Donc, dans votre cas:

hsh.sort_by {|key, ratings| ratings[:rating] } 
+0

@Gaius - merci pour l'édition, mais le code fonctionne comme écrit. Tout mon point était que #sort_by fait implicitement la conversion Array sans que vous ayez à coller le .to_a dedans - même dans Ruby 1.8 – Gareth

3

il pourrait y avoir une meilleure structure de données, mais (je suppose que ce rubis), il est possible de le faire en Ruby en utilisant le style de tri en ligne pour dire, fondamentalement, il comment comparer les deux. Voici un exemple concret:

my_hash = { 
    55 => {:value=>61, :rating=>-147}, 
    89 => {:value=>72, :rating=>-175}, 
    78 => {:value=>64, :rating=>-155}, 
    84 => {:value=>90, :rating=>-220}, 
    95 => {:value=>39, :rating=>-92}, 
    46 => {:value=>97, :rating=>-237}, 
    52 => {:value=>73, :rating=>-177}, 
    64 => {:value=>69, :rating=>-167}, 
    86 => {:value=>68, :rating=>-165}, 
    53 => {:value=>20, :rating=>-45} 
} 

puts "MY HASH" 
my_hash.each do |local| 
    puts local 
end 

sorted_hash = my_hash.sort { | leftval, rightval | rightval[1][:rating]<=>leftval[1][:rating] } 

puts "SORTED HASH" 
sorted_hash.each do |local| 
    puts local 
end 
+0

Cela ne fera pas beaucoup de différence ici, mais #sort est généralement inefficace avec les champs calculés. En effet, il recalculera les critères de tri pour * chaque * comparaison. #sort_by calcule les critères une seule fois pour chaque élément du tableau original – Gareth