简体   繁体   中英

Put every Hash Element inside of an Array Ruby

Let's say I have a Hash like this:

my_hash = {"a"=>{"a1"=>"b1"}, "b"=>"b", "c"=>{"c1"=>{"c2"=>"c3"}}}

And I want to convert every element inside the hash that is also a hash to be placed inside of an Array.

For example, I want the finished Hash to look like this:

{"a"=>[{"a1"=>"b1"}], "b"=>"b", "c"=>[{"c1"=>[{"c2"=>"c3"}]}]}

Here is what I've tried so far, but I need it to work recursively and I'm not quite sure how to make that work:

my_hash.each do |k,v|
  if v.class == Hash
    my_hash[k] = [] << v
  end
end
 => {"a"=>[{"a1"=>"b1"}], "b"=>"b", "c"=>[{"c1"=>{"c2"=>"c3"}}]}

You need to wrap your code into a method and call it recursively.

my_hash = {"a"=>{"a1"=>"b1"}, "b"=>"b", "c"=>{"c1"=>{"c2"=>"c3"}}}

def process(hash)
    hash.each do |k,v|
      if v.class == Hash
        hash[k] = [] << process(v)
      end
    end
end

p process(my_hash)
#=> {"a"=>[{"a1"=>"b1"}], "b"=>"b", "c"=>[{"c1"=>[{"c2"=>"c3"}]}]}

Recurring proc is another way around:

h = {"a"=>{"a1"=>"b1"}, "b"=>"b", "c"=>{"c1"=>{"c2"=>"c3"}}}
h.map(&(p = proc{|k,v| {k => v.is_a?(Hash) ? [p[*v]] : v}}))
 .reduce({}, &:merge)
# => {"a"=>[{"a1"=>"b1"}], "b"=>"b", "c"=>[{"c1"=>[{"c2"=>"c3"}]}]}

It can be done with single reduce, but that way things get even more obfuscated.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM