2011-10-04 5 views
4

Existe-t-il un moyen rapide d'obtenir une permutation (aléatoire) d'un hachage donné? Par exemple avec les tableaux que je peux utiliser la méthode sample comme dansRuby hash permutation

ruby-1.9.2-p180 :031 > a = (1..5).to_a 
=> [1, 2, 3, 4, 5] 
ruby-1.9.2-p180 :032 > a.sample(a.length) 
=> [3, 5, 1, 2, 4] 

Pour hash je peux utiliser la même méthode sur les touches de hachage et de construire un nouveau hachage avec

ruby-1.9.2-p180 :036 > h = { 1 => 'a', 2 => 'b', 3 => 'c' } 
=> {1=>"a", 2=>"b", 3=>"c"} 
ruby-1.9.2-p180 :037 > h.keys.sample(h.length).inject({}) { |h2, k| h2[k] = h[k]; h2 } 
=> {3=>"c", 2=>"b", 1=>"a"} 

mais c'est si laid. Existe-t-il une méthode «échantillon» pour les hachages qui peut éviter tout ce code?

Mise à jour Comme l'a souligné @Michael Kohl dans les commentaires, cette question n'a de sens que pour ruby ​​1.9.x. Etant donné que dans 1.8.x Hash n'est pas ordonné, il n'y a aucun moyen de le faire.

+1

Quel est le but de tout cela? Dans 1.8 hachages sont non ordonnés et dans 1.9 ordonné par ordre d'insertion. –

+1

@Michael: On dirait qu'il utilise le 1.9, donc mélanger un Hash a du sens puisque 'h.each' a un ordre bien défini. –

+0

@MichaelKohl c'est juste une curiosité. De plus, même avec les hachages 1.8 non ordonnés, cette méthode retournera un ordre différent à la place de l'ordre déterministe et fixe. Pensez-y comme un remaniement pour la classe de hachage. – Fabio

Répondre

9

Une légère amélioration de la mu est réponse trop courte:

h = Hash[h.to_a.shuffle] 
+1

+1 pour un raffinement intéressant. –

4

il suffit d'ajouter un to_a et Hash[] à votre version de tableau pour obtenir une version Hash:

h = Hash[h.to_a.sample(h.length)] 

Par exemple:

>> h = { 1 => 'a', 2 => 'b', 3 => 'c' } 
=> {1=>"a", 2=>"b", 3=>"c"} 
>> h = Hash[h.to_a.sample(h.length)] 
=> {2=>"b", 1=>"a", 3=>"c"} 
+0

Très gentil, merci. – Fabio

+1

'h = Hash [h.to_a.shuffle]' – steenslag

+1

@steenslag: Cela ressemble à une réponse (et une bonne réponse), vous devriez le mettre comme tel. –

0

Avez-vous vraiment besoin de mélanger ou avez-vous juste besoin d'un moyen d'accès/itérer sur un clé aléatoire?

Sinon, une solution peut-être moins coûteuse serait de mélanger les clés de hachage et accéder à vos éléments en fonction de la permutation de ces clés de hachage

h = your_hash 
shuffled_hash_keys = hash.keys.shuffle 

shuffled_hash_keys.each do |key| 
    # do something with h[key] 
end 

Je crois (mais aurait besoin d'une preuve d'un indice de référence) que cela évite le besoin/le coût de construire un nouveau hachage et est probablement plus efficace si vous avez de gros hachages (il vous suffit de payer le coût d'une permutation de matrice)