Arrays 如何对散列进行数组包装

Arrays 如何对散列进行数组包装,arrays,ruby,hash,Arrays,Ruby,Hash,我想要 inv = {"C"=>{"CPS"=>{"CP"=>{"name"=>"a"}}}} is my object 我试过了 inv = {"C"=>{"CPS"=>{"CP"=>[{"name"=>"a"}]}}} 但是仍然inv={“C”=>{“CPS”=>{“CP”=>{“name”=>“a”}}} 尝试映射也这应该可以做到: inv["C"]["CPS"].inject({}) do |result, (k, v)| k =

我想要

inv = {"C"=>{"CPS"=>{"CP"=>{"name"=>"a"}}}} is my object
我试过了

inv = {"C"=>{"CPS"=>{"CP"=>[{"name"=>"a"}]}}}
但是仍然
inv={“C”=>{“CPS”=>{“CP”=>{“name”=>“a”}}}

尝试
映射

这应该可以做到:

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

=>  [{"name"=>"a"}]
基本上

  • 获取值
  • 转换为数组
  • 设置值
  • 此处不需要迭代,即
    map
    reduce

    这应该可以做到:

    inv["C"]["CPS"].inject({}) do |result, (k, v)|
      k = Array.wrap(v)
    end
    
    =>  [{"name"=>"a"}]
    
    基本上

  • 获取值
  • 转换为数组
  • 设置值

  • 这里不需要迭代,即
    map
    reduce
    另一个选项是使用
    点击

    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"}] }}}
    
    点击
    将生成当前对象,以便您可以在适当位置对其进行修改

    更新

    受@CarySwoveland更广泛应用的启发,您也可以使用类似的东西

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

    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
    
    这假设在整个层次结构中都是唯一的键,否则相同名称的嵌套键将以相同的方式自下而上包装。 e、 g


    另一个选项是使用
    点击

    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"}] }}}
    
    点击
    将生成当前对象,以便您可以在适当位置对其进行修改

    更新

    受@CarySwoveland更广泛应用的启发,您也可以使用类似的东西

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

    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
    
    这假设在整个层次结构中都是唯一的键,否则相同名称的嵌套键将以相同的方式自下而上包装。 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" 
            ]
          }
        }
    

    我建议您使用递归,它是一种紧凑且易于阅读的方法,比只处理特定哈希的解决方案有更广泛的应用

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

    谢谢那很有帮助,汉克斯!这有助于感谢共享,这是一个有用的嵌套模式hashes@maxpleaner更新了我的答案,提供了一个更灵活的版本。感谢分享这是一个有用的嵌套模式hashes@maxpleaner更新了我的答案,提供了一个更灵活的版本。虽然这似乎没有产生预期的结果,但你确实激励我写了一篇文章更灵活的版本查看我的更新答案。虽然这似乎没有产生预期的结果,但您确实鼓励我编写更灵活的版本查看我的更新答案。不要忘记通过单击复选标记实际接受答案。这允许问题显示为已回答。你似乎利用这个社区来获得答案,但习惯性地放弃了接受正确答案的尊重。不要忘记通过点击复选标记来实际接受答案。这允许问题显示为已回答。你似乎利用这个社区来寻找答案,但习惯性地放弃了接受这些答案的尊重。