I have the following:
{ :a_b_c => 42, :a_b_d => 67, :a_d => 89, :e => 90 }
How do I convert this as below
{ a: { b: { c: 42, d: 67 }, d: 89 }, e: 90 }
CodePudding user response:
Rails with ActiveSupport have Hash#deep_merge
and Hash#deep_merge!
If you haven't them, you can define
class Hash
def deep_merge(other_hash, &block)
dup.deep_merge!(other_hash, &block)
end
def deep_merge!(other_hash, &block)
merge!(other_hash) do |key, this_val, other_val|
if this_val.is_a?(Hash) && other_val.is_a?(Hash)
this_val.deep_merge(other_val, &block)
elsif block_given?
block.call(key, this_val, other_val)
else
other_val
end
end
end
end
Or just require these methods
require 'active_support/core_ext/hash/deep_merge'
And finally
hash =
{ :a_b_c => 42, :a_b_d => 67, :a_d => 89, :e => 90 }
hash.each_with_object({}) do |(k, v), h|
h.deep_merge!(k.to_s.split('_').map(&:to_sym).reverse.reduce(v) { |assigned_value, key| { key => assigned_value } })
end
# => {:a=>{:b=>{:c=>42, :d=>67}, :d=>89}, :e=>90}