How to recursively collect deeply nested keys with ruby hash
I'm looking for a clever way to collect the parent keys of a deeply nested key and assign them as value. eg...
take the hash as ...
{
:foo => {
:bar => {
:baz => 'a',
:bez => 'b',
:biz => 'c'
}
}
}
and create a hash from this like this ...
{ :foo => { :bar => { :baz => [:foo, :bar, :baz], :bez => [:foo, :bar, :bez], :biz => [:foo, :bar, :biz] } } }
+3
source to share
3 answers
Try a recursive solution:
# array of parent keys initially []
def nested(hash, keys = [])
# go through each key-value pair
hash.each do |key, val|
# if the value is a Hash, recurse and
# add the key to the array of parents
if val.is_a? Hash
nested(val, keys.push(key))
# remove last parent when we're done
# with this pair
keys.pop
else
# if the value is not a Hash, set the
# value to parents + current key
hash[key] = keys + [key]
end
end
end
+2
source to share
Make a recursive function.
def recurse(h, acc=[])
Hash[h.map { |key, value|
if value.is_a? Hash
[key, recurse(value, acc + [key])]
else
[key, acc + [key]]
end
}]
# You can use h.map {...}.to_h in Ruby 2.1+
end
recurse({
:foo => {
:bar => {
:baz => 'a',
:bez => 'b',
:biz => 'c'
}
}
})
# => {:foo=>
# {:bar=>
# {:baz=>[:foo, :bar, :baz],
# :bez=>[:foo, :bar, :bez],
# :biz=>[:foo, :bar, :biz]}}}
+1
source to share
I suggest the following recursion.
code
def rehash(h, keys = [])
h.each_with_object({}) { |(k,v),g|
g[k] = case v
when Hash then rehash(v, keys+[k])
else (keys + [k])
end
}
end
Example
h = { :foo => {
:bar => {
:baz => 'a',
:bez => 'b',
:biz => 'c'
}
}
}
rehash(h)
#=> {:foo=>
{:bar=>
{:baz=>[:foo, :bar, :baz],
:bez=>[:foo, :bar, :bez],
:biz=>[:foo, :bar, :biz]}}}
+1
source to share