2010-06-30 8 views
2

Je migre mon code PHP vers Ruby et à un moment donné j'ai besoin de mettre à jour les éléments de hachage à l'intérieur d'une boucle. Par exemple:Comment mettre à jour un objet de hachage Ruby à l'intérieur d'une boucle sur ce hachage?

compositions.each_pair do |element,params| 
    params['composition'].each_pair do |item,data| 
    data['af'] /= params['af sum'] 
    data['mf'] /= params['mass'] 
    end 
end 

Je pourrais le faire en utilisant des index d'éléments, mais ce sera moche. Existe-t-il un moyen agréable de lier les variables de boucle aux éléments de hachage correspondants? En PHP, j'écrirais &$params et &$data dans les boucles correspondantes. Ou peut-être une meilleure suggestion?


Mise à jour

Deux tests pour démontrer le problème. La première:

a={'a'=>1, 'b'=>2, 'c'=>3} 

a.each_pair do |k,v| 
    v += 1 
end 
p a # => {"a"=>1, "b"=>2, "c"=>3} 

et le second

a.each_pair do |k,v| 
    a[k] += 1 
end 
p a # => {"a"=>2, "b"=>3, "c"=>4} 

Update2

Merci à Mladen (voir ci-dessous), j'ai compris la différence entre ces deux cas. Cependant, j'ai encore une question: comment mettre à jour data article (pas seulement ses propres articles)? Disons que nous ajoutons

data = data['af'] + data['mf'] 

à la boucle interne.

+1

Quel est le problème avec le code ci-dessus? En outre, vous pouvez publier un exemple de structure de données. –

+0

Le code ne met pas à jour 'compositions [élément] ['composition'] [item] ['af']' et l'autre parce qu'il n'y a pas de lien entre les variables de la boucle et le hash – Andrei

+1

Comment l'avez-vous testé? ? Il doit mettre à jour 'compositions [element] ['composition'] [item] ['af']' parce que 'data' est juste une référence à' compositions [élément] ['composition'] [item] 'et' data [' foo '] =' quelquechose 'va modifier la structure de données 'compositions'. – BaroqueBobcat

Répondre

2

Il semble que le code de la question fonctionne bien:

compositions = {1 => {'af sum' => 100.0, 'mass' => 200.0, 'composition' => {1 => {'af' => 5.0, 'mf' => 6.0}, 2 => {'af' => 7.0, 'mf' => 8.0}, 3 => {'af' => 9.0, 'mf' => 16.0}}}} 
#=> {1=>{"af sum"=>100.0, "mass"=>200.0, "composition"=>{1=>{"af"=>5.0, "mf"=>6.0}, 2=>{"af"=>7.0, "mf"=>8.0}, 3=>{"af"=>9.0, "mf"=>16.0}}}} 
compositions.each_pair do |element,params| 
    params['composition'].each_pair do |item,data| 
    data['af'] /= params['af sum'] 
    data['mf'] /= params['mass'] 
    end 
end 
#=> {1=>{"af sum"=>100.0, "mass"=>200.0, "composition"=>{1=>{"af"=>0.05, "mf"=>0.03}, 2=>{"af"=>0.07, "mf"=>0.04}, 3=>{"af"=>0.09, "mf"=>0.08}}}} 

Mais la structure exemple est assez bien deviné à partir du code, OP devrait afficher un exemple, il travaille avec afin que nous puissions réellement faire des progrès .

Edit:

Lorsque vous effectuez méthode + sur un entier, un nouvel objet est retourné en conséquence. Cet objet est affecté à v dans votre premier exemple, mais pas affecté au hachage, il n'est donc pas conservé. Dans votre second exemple, vous l'assignez au hachage. Cependant, si vous travaillez avec des méthodes de mutation, vous modifiez les objets mêmes sur place, vous n'avez donc pas besoin de les réaffecter au hachage. Par exemple:

{1 => 'foo', 2 => 'bar'}.each{|k,v| v.swapcase!} 
#=> {1=>"FOO", 2=>"BAR"} 

mais

{1 => 'foo', 2 => 'bar'}.each{|k,v| v = 'baz'} 
#=> {1=>"foo", 2=>"bar"} 

Edit 2:

Je pense que vous avez mal à comprendre ce que k et v dans les exemples sont. Ce ne sont que des variables locales dans le bloc, ils commencent par référencer tout ce qui est dans le hachage, mais que font-ils référence peut être changé au cours d'un bloc comme avec n'importe quelle autre variable. Ce changement ne reflétera pas le hachage. Vous devez modifier l'objet même, pas la référence, pour le changer réellement.

Jetez un oeil à cela, par exemple encore plus simple, pas de hash, blocs charabia:

a = 5 
b = a 
b += 1 
a # => 5 
b # => 6 

Il est aussi simple que cela.

+0

Hmm, maintenant je suis très confus. Pourriez-vous s'il vous plaît exécuter les exemples que j'ai ajoutés récemment? – Andrei

+1

J'ai développé la réponse. –

+0

Ok, je suis encore confus, mais il y a une bonne tendance. Il est vrai que je n'ai pas exécuté mon exemple original en supposant que cela ne marchera pas, puisque le premier simple n'a pas réussi. Désolé pour ça. Si je comprends bien, la méthode 'data ['mf']/= params ['mass']' est "mutante" et 'data ['mf']/= 9' ne l'est pas. Est-ce correct? Comment puis-je faire la dernière mutation? Comme ceci 'data ['mf'] = data ['mf']. Divide_by (9)'? – Andrei

Questions connexes