什么是在Ruby中嵌套哈希中修改数组内部哈希的优雅方法

时间:2013-11-21 21:14:25

标签: ruby-on-rails ruby arrays hash key-value

我想改变这个

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”返回的具体细节(重要的是它取决于最外面的键和内部名称值,在本例中),是否有任何替代方案可以被认为更优雅?

1 个答案:

答案 0 :(得分:0)

为什么不做递归函数?

def add_siniter(hash) 
  hash[:siniter_name] = "#{hash['name']}_i_love_hashes"
  hash
end

def format_hash(item)
  case item
    when Hash  then item.keys.each{|key| format_hash(item[key])}
    when Array then item.map!{|h| add_siniter(h)}
  end
end

format_hash(a_hash)