如何array_wrap散列哈希值

时间:2016-08-30 18:07:54

标签: arrays ruby hash

inv = {"C"=>{"CPS"=>{"CP"=>{"name"=>"a"}}}} is my object

我想要

inv = {"C"=>{"CPS"=>{"CP"=>[{"name"=>"a"}]}}}

我试过

inv["C"]["CPS"].inject({}) do |result, (k, v)|
  k = Array.wrap(v)
end

=>  [{"name"=>"a"}]

但仍然是inv={"C"=>{"CPS"=>{"CP"=>{"name"=>"a"}}}}

尝试map

3 个答案:

答案 0 :(得分:3)

另一种选择是使用tap

inv["C"]["CPS"].tap do |h|
  h["CP"] = [h["CP"]] #or Array.wrap(h["CP"]) in rails
end
inv
#=> {"C"=>{"CPS"=>{"CP"=>[{"name"=>"a"}]}}} 

tap将生成当前对象,以便您可以对其进行修改。

<强>更新

受@ CarySwoveland更广泛应用程序的启发,你也可以使用这样的东西。

class HashWrapper
  attr_reader :original_hash
  attr_accessor :target_keys

  def initialize(h,*target_keys)
    @original_hash = h 
    @target_keys = target_keys
  end

  def wrapped_hash
    @wrapped_hash ||= {}
  end

  def wrap_me
    original_hash.each do |k,v|
      value = v.is_a?(Hash) ? HashWrapper.new(v,*target_keys).wrap_me : v
      wrapped_hash[k] = wrap(k,value)
    end
    wrapped_hash
  end
private
  def wrap(k,v)
    target_keys.include?(k) ? [v] : v
  end
end

然后实施如下

wrapper = HashWrapper.new(inv,"CP")
wrapper.wrap_me
#=> {"C"=>
      {"CPS"=>
        {"CP"=>
           [
            {"name"=>"a"}
           ]
        }
      }
    } 
new_wrapper = HashWrapper.new(inv,"CP","CPS")
new_wrapper.wrap_me
#=> {"C"=>
      {"CPS"=>
         [
           {"CP"=>
             [
              {"name"=>"a"}
             ]
           }
         ]
      }
    }

这假定在层次结构中一直有唯一的键,否则同名的嵌套键将从下到上以相同的方式包装。 e.g。

inv = {"C"=>{"CPS"=>{"CP"=>{"name"=>"a"}},"CP" => "higher level"}}
HashWrapper.new(inv,"CP").wrap_me
#=> {"C"=>
      {"CPS"=>
        {"CP"=>
           [
             {"name"=>"a"}
           ]
      }, 
      "CP"=>
        [
         "higher level" 
        ]
      }
    }

答案 1 :(得分:0)

这应该这样做:

hash = {"C"=>{"CPS"=>{"CP"=>{"name"=>"a"}}}}
val = hash["C"]["CPS"]["CP"]
val_as_arr = [val] # can optionally call flatten here
hash["C"]["CPS"]["CP"] = val_as_arr
puts hash
# => {"C"=>{"CPS"=>{"CP"=> [{"name" => "a"}] }}}

基本上

  1. 获取值
  2. 转换为数组
  3. 设置值
  4. 此处不需要迭代,即mapreduce

答案 2 :(得分:0)

我建议你以一种紧凑且易于阅读的方式使用递归,这种方法比只适用于你的特定哈希的解决方案具有更广泛的应用。

def wrap_it(h)
  h.each { |k,v| h[k] = v.is_a?(Hash) ? wrap_it(v) : [v] }
  h
end

h = { "C"=>{ "CPS"=>{ "CP"=>{ "name"=>"a" } } } }
wrap_it(h)
  #=> {"C"=>{"CPS"=>{"CP"=>{"name"=>["a"]}}}}

h = { "C"=>{ "CPS"=>{ "CP"=>{ "CPPS"=> { "name"=>"cat" } } } } }
wrap_it(h)
  #=> {"C"=>{"CPS"=>{"CP"=>{"CPPS"=>{"name"=>["cat"]}}}}}

h = { "C"=>{ "CPS"=>{ "CP"=>{ "CPPS"=> { "name"=>"cat" } },
                      "DP"=>{ "CPPPS"=>"dog" } } } }
wrap_it(h)
  #=> {"C"=>{"CPS"=>{"CP"=>{"CPPS"=>{"name"=>["cat"]}}, "DP"=>{"CPPPS"=>["dog"]}}}}