3

I have a hash in the database in JSON format. eg

{
  "one" => {
    "two" => {
      "three" => {}
    }
  } 
}

I need to generate this from a string. The above example would be generated from the string "one.two.three".

Firstly how would I do this?

Second part of the problem. I will be receiving multiple strings - each one building on the last. So if I get "one.two.three", then "one.two.four", I hash to be this:

{
  "one" => {
    "two" => {
      "three" => {},
      "four" => {}
    }
  } 
}

And if I get "one.two.three" twice, I want the latest "three" value to override what was there. Strings can also be of any length (e.g. "one.two.three.four.five" or just "one"). Hopefully that makes sense?

Plattsy
  • 515
  • 4
  • 12
  • 1
    Just split and make recursive hashes. There are multiple deep-merge examples on the web, including a gem or two; I'd probably just search for those first--I don't recall their names at the moment. – Dave Newton Aug 14 '12 at 00:58
  • I'll try some of those deep-merge Hash methods. Though do you know off the top of your hread how do go from "one.two.three" to hash["one"]["two"]["three"]? I know you can go "one.two.three".split(".") to get the array. – Plattsy Aug 14 '12 at 01:10

1 Answers1

13

To generate nested hash:

hash = {}

"one.two.three".split('.').reduce(hash) { |h,m| h[m] = {} }

puts hash #=> {"one"=>{"two"=>{"three"=>{}}}}

If you don't have rails installed then install activesupport gem:

gem install activesupport

Then include it into your file:

require 'active_support/core_ext/hash/deep_merge'

hash = {
  "one" => {
    "two" => {
      "three" => {}
    }
  } 
}.deep_merge(another_hash)

The access to the internals would be:

hash['one']['two']['three'] #=> {}
megas
  • 21,401
  • 12
  • 79
  • 130
  • I didn't know about deep_merge - thanks. Can you give me a good way of turning "one.two.three" to hash["one"]["two"]["three"]? – Plattsy Aug 14 '12 at 01:25
  • 1
    If you use `h[m] ||= {}` in your reduce block, you can get rid of the deep merge altogether as it will merge it automatically when feeding the existing hash into the `reduce` again. This however only works if you have only hashes (and not e.g. Arrays). – Holger Just Aug 14 '12 at 16:09
  • OK cool, so what would be the easiest way to merge a whole bunch of hashes with each other? (i.e. not just a.deep_merge(b), but [a,b,c,d].deep_merge) – thoughtpunch Dec 05 '12 at 19:12
  • I don't understand your question, maybe you want create new one? – megas Dec 05 '12 at 19:57