Php 如何更新循环中的Ruby哈希项?

Php 如何更新循环中的Ruby哈希项?,php,ruby,variables,hash,loops,Php,Ruby,Variables,Hash,Loops,我正在将我的PHP代码迁移到Ruby,在某个时候我需要更新循环中的哈希元素。例如: 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 => 'foo', 2 => 'bar'}.each{

我正在将我的PHP代码迁移到Ruby,在某个时候我需要更新循环中的哈希元素。例如:

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 => 'foo', 2 => 'bar'}.each{|k,v| v.swapcase!}
#=> {1=>"FOO", 2=>"BAR"}
我可以使用项目索引,但它会很难看。是否有一种很好的方法将循环变量链接到相应的哈希项?在PHP中,我将在相应的循环中编写
&$params
&$data
。还是一个更好的建议


更新

两个测试来证明这个问题。第一个:

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

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

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

更新2

多亏了姆拉登(见下文),我理解了这两种情况之间的区别。但是,我仍然有一个问题:如何更新
数据
项(而不仅仅是它自己的项)?假设我们加上

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

到内部循环。

问题中的代码似乎工作正常:

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}}}}
但是示例结构基本上是从代码中猜出来的,OP应该发布一个他正在使用的示例,这样我们就可以实际取得一些进展

编辑:

当您对整数执行
+
方法时,结果将返回一个新对象。在第一个示例中,该对象被分配给
v
,但没有分配回哈希,因此它不会被保留。在第二个示例中,将其分配回哈希

但是,如果您使用变异方法,您就可以在适当的位置更改对象,这样就不需要将它们重新分配给散列。例如:

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 => 'foo', 2 => 'bar'}.each{|k,v| v.swapcase!}
#=> {1=>"FOO", 2=>"BAR"}
但是

编辑2:

我认为您在理解示例中的
k
v
时存在问题。它们只是块中的局部变量,它们从引用散列中的任何内容开始,但它们引用的内容可以在块的过程中更改,就像使用任何其他变量一样。这种变化不会反映到散列中。您需要更改对象本身,而不是对它的引用,才能真正更改它

看一看这个更简单的例子,没有散列,块混乱:

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

就这么简单。

上面的代码有什么问题?另外,您可以发布一个数据结构示例。代码不会更新
compositions[element]['composition'][item]['af']
和另一个,因为循环变量和原始哈希之间没有反向链接。您如何测试它?它应该更新
compositions[element]['composition'][item]['af']
,因为
data
只是对
compositions[element]['composition'][item]
的引用,而
data['foo']='something
将改变
compositions
数据结构。请看一下这个例子,我刚才补充了我的问题。请注意,它非常类似于PHP循环
foreach
,其中可以指定是否将循环变量链接到原始哈希/数组(该功能已添加到PHP v.5中),我认为您必须使用第二种方法。怎么了?嗯,现在我很困惑。请运行我最近添加的示例好吗?
data['mf']/=params['mass']
只是
data['mf']=data['mf']/=params['mass']
的简写,因此它正在执行您需要的赋值,以便在散列中记住值。顺便说一句,我在答案中添加了一些内容。
数据
引用了一个散列元素(也就是散列)。执行
data['mf']=data['mf']/params['mass']
时,将
data
散列中的值字段中的内容置于
'mf'
键下,将其除以,然后重新分配。您没有将
数据
更改为引用,而是更改了它所引用的对象。如果“更新”的意思是“将哈希
参数['composition']
中的值替换为
中的
其他内容
”,则您需要准确地执行该操作:
参数['composition'][item]=something\u other
。一个新的操作符在这方面帮不了你(顺便说一句,操作符在Ruby中只不过是方法,所以我们Ruby人不必等到有人在那里“向语言添加一个新的操作符”,每个人都可以自由地实现它们)
data
是一个局部变量,在Ruby中无法获得“引用到引用”这样的东西。另外,
[]
[]=
实际上是
散列
类的方法,因此在调用
每个
并获取块中的键和值时,不会发生特殊的魔法。但那是另一个故事。