我有一系列哈希:
data1 = [{:first => 1, :second => 'whatever'},{:first => 2, :second => 'something'}]
test_merge = {'whatever' => {:third => 1, :fourth => 1}, 'something' => {:third => 2, :fourth => 2}}
我想要这个输出:
[{:first=>"MODIFIED", :second=>"whatever", :test_field=>"added", :third=>1, :fourth=>1, "sdsds"=>"sdsds", "2x4"=>8}, {:first=>"MODIFIED", :second=>"something", :test_field=>"added", :third=>2, :fourth=>2, "sdsds"=>"sdsds", "2x4"=>8}]
我做了地图和合并:
data2 = data1.map do |d|
d[:test_field] = 'added'
d[:first] = 'MODIFIED'
d2 = test_merge[d[:second]]
d = d.merge(d2)
d['sdsds'] = 'sdsds'
d['2x4'] = 2*4
end
我得到了:
data1 #=> [{:first=>"MODIFIED", :second=>"whatever", :test_field=>"added"}, {:first=>"MODIFIED", :second=>"something", :test_field=>"added"}]
data2 #=> [8, 8]
如果我这样做可以修复
data2 = data1.map do |d|
d[:test_field] = 'added'
d[:first] = 'MODIFIED'
d2 = {:test_field_two => 'notadded'}
d = d.merge(d2)
d['sdsds'] = 'sdsds'
d['2x4'] = 2*4
d #or d=d
end
但为什么我必须在最后d
或d
插入d=d
?最后写d
看起来很难看。是不是有另一种方法可以做到,我想要如上所述的确切输出?
编辑:2017年1月3日(如果您是第一次阅读此问题,请不要阅读此编辑内容,上面提到了所有内容)
我必须在.map
中使用merge,因为我有另一个哈希如下:
test_merge = {'whatever' => {:third => 1, :fourth => 1}, 'something' => {:third => 2, :fourth => 2}}
需要在.each中合并这样(合并在.each中不起作用,所以我必须使用map)或.map
d = d.merge(test_merge[d[:second]])
此外,'2x4'
,:first
和其他密钥也很重要,需要设置/修改。
如果我需要修改d [:first],它应该被修改。
我试过史蒂夫提到的.each
,
data1 = [{:first => 1, :second => 'whatever'},{:first => 2, :second => 'something'}]
test_merge = {'whatever' => {:third => 1, :fourth => 1}, 'something' => {:third => 2, :fourth => 2}}
data1.each do |d|
d[:test_field] = 'added'
d[:first] = 'MODIFIED'
d2 = test_merge[d[:second]]
d = d.merge(d2)
d['sdsds'] = 'sdsds'
d['2x4'] = 2*4
end
这是我得到的结果:
[{:first=>"MODIFIED", :second=>"whatever", :test_field=>"added"}, {:first=>"MODIFIED", :second=>"something", :test_field=>"added"}]
这不是我预期的输出。这有什么黑客攻击吗?
答案 0 :(得分:3)
使用块执行map
时,块的最后执行行是在新数组中返回的内容。
所以如果最后一行是......
d['2x4'] = 2*4
然后它返回了2 * 4(8)。
将块的最后一行设置为...
d
...表示返回d
变量(整个哈希)的值。
如果您只想更改哈希值并且不需要返回数组,则不需要使用map
。请改用each
。 (编辑时考虑到Eric关于浅层复制的观察结果)。
data2 = data1.map{|d| d.dup}
data2.each do |d|
d[:test_field] = 'added'
d[:test_field_two] = 'notadded'
d['sdsds'] = 'sdsds'
d['2x4'] = 2*4
end
答案 1 :(得分:1)
Hash#merge
返回合并的Hash而不更改原始的Hash,因此您可以添加新的|key,value|
对并直接返回所需的哈希:
data2 = data1.map do |h1|
h1.merge(:test_field => 'added',
:test_field_two => 'not_added',
'sdsds' => 'sdsds',
'2x4' => 2 * 4)
end
data2
现在是:
[{:first=>1,
:second=>"whatever",
:test_field=>"added",
:test_field_two=>"not_added",
"sdsds"=>"sdsds",
"2x4"=>8},
{:first=>2,
:second=>"something",
:test_field=>"added",
:test_field_two=>"not_added",
"sdsds"=>"sdsds",
"2x4"=>8}]
虽然data1
仍然是:
[{:first=>1, :second=>"whatever"}, {:first=>2, :second=>"something"}]
答案 2 :(得分:0)
我认为这可能会更好!虽然我不确定我是否正确理解了这个问题。希望这会有所帮助。
data1 = [{:first => 1, :second => 'whatever'},{:first => 2, :second => 'something'}]
d2 = {:test_field_two => 'notadded', "sdsds"=>"sdsds", "2x4"=>2*4}
data2 = data1.map do |d| d.merge(d2) end
#=> [{:first=>1, :second=>"whatever", :test_field_two=>"notadded", "sdsds"=>"sdsds", "2x4"=>8}, {:first=>2, :second=>"something", :test_field_two=>"notadded", "sdsds"=>"sdsds", "2x4"=>8}]