Home > database >  Ruby convert flattened hash to nested hash
Ruby convert flattened hash to nested hash

Time:09-20

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}
  •  Tags:  
  • ruby
  • Related