【发布时间】:2013-12-06 13:47:39
【问题描述】:
我想改造一下
def some_process(k,v)
return "#{v}_#{k}"
end
a_hash = {
"i_love_hashes" => {
"thing" => 20,
"other_thing" => "0",
"yet_another_thing" => "i disagree",
"_peculiar_thing" => [
{"count" => 30,
"name" => "freddie"},
{"count" => 15,
"name" => "johhno"},
{"count" => 12,
"name" => "mohammed"},
]
},
"as_do_i" => {
"thing" => 10,
"other_thing" => "2",
"yet_another_thing" => "i strongly agree",
"_peculiar_thing" => [
{"count" => 10,
"name" => "frodo"},
{"count" => 4,
"name" => "bilbo"},
{"count" => 2,
"name" => "elizabeth"},
]
}
}
进入这个
{
"i_love_hashes"=>{
"thing"=>20,
"other_thing"=>"0",
"yet_another_thing"=>"i disagree",
"_peculiar_thing"=> [
{"count"=>30, "name"=>"freddie", :sinister_name=>"freddie_i_love_hashes"},
{"count"=>15, "name"=>"johhno", :sinister_name=>"johhno_i_love_hashes"},
{"count"=>12, "name"=>"mohammed", :sinister_name=>"mohammed_i_love_hashes"}
]},
"as_do_i"=>{
"thing"=>10,
"other_thing"=>"2",
"yet_another_thing"=>"i strongly agree",
"_peculiar_thing"=>[
{"count"=>10, "name"=>"frodo", :sinister_name=>"frodo_as_do_i"},
{"count"=>4, "name"=>"bilbo", :sinister_name=>"bilbo_as_do_i"},
{"count"=>2, "name"=>"elizabeth", :sinister_name=>"elizabeth_as_do_i"}
]
}
}
这是我目前用来实现此目的的代码
a_hash.each_with_object({}) do |(k,v),o|
o.merge!({k =>
v.each_with_object({}) do |(a,b),g|
g.merge!({ a =>
(b.is_a?(Array) ? b.collect {|x| x.merge({sinister_name: (some_process k, x["name"])})} : b)
})
end
})
end
忽略“some_process”返回的具体细节(重要的是它取决于最外层的键和内部名称值,在这个例子中),有没有被认为更优雅的替代方案?
【问题讨论】:
-
为什么是
.each_with_object()而不是inject()? -
-
@Phlip:等效的基于注入的版本是什么?
-
事实证明,stackoverflow.com/questions/5481009/…,
each_with_object只是inject,而不需要在每个块的末尾返回哈希值(在你的情况下)。 -
假设我可以将你的算法写成
a_hash.each do |key, value| value['_peculiar_thing'].map do |h| h.merge! :sinister_name => "#{ h['name'] }_i_love_hashes" end end,如果我不介意踩你的输入a_hash,你也可以完全省去each_with_object,而只是深度克隆a_hash在你开始前。如果你介意它会被踩到。
标签: ruby-on-rails ruby arrays hash key-value