【问题标题】:What is an elegant way of modifying hashes inside an array within a nested hash in Ruby什么是在Ruby中的嵌套哈希中修改数组内的哈希的优雅方法
【发布时间】: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


【解决方案1】:

为什么不做一个递归函数?

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)

【讨论】:

  • 虽然我喜欢递归方法的想法,但在这种情况下,需要向下传递顶级键以及深度参数才能使其工作。
  • 此外,您提供的 format_hash 方法在使用提供的哈希运行时似乎只返回两个顶级键的数组。
猜你喜欢
  • 1970-01-01
  • 2011-07-19
  • 2016-12-31
  • 2018-04-24
  • 1970-01-01
  • 2021-02-05
  • 1970-01-01
  • 2019-11-21
  • 1970-01-01
相关资源
最近更新 更多