I have a string foo.bar.baz
with a value 'qux' that I want to convert to a nested hash like so:
{
foo: {
bar: {
baz: 'qux'
}
}
}
How would I do this in a way that would allow for different string lengths? e.g. foo.bar
or foo.bar.baz.qux
CodePudding user response:
First of all, you have to split
the string. You can then use inject
to build the structure. Because the hash is built from the inside out, we have to reverse
the initial array:
'foo.bar.baz'.split('.') #=> ["foo", "bar", "baz"]
.reverse #=> ["baz", "bar", "foo"]
.inject('qux') { |memo, key| { key.to_sym => memo } }
#=> {:foo=>{:bar=>{:baz=>"qux"}}}
It might not be obvious how this works. On the first invocation, memo
is 'qux'
and key
is 'baz'
. The block turns this into {:baz=>'qux'}
which then becomes the new memo
.
Step by step:
memo key result
--------------------------------------------------------------
'qux' 'baz' {:baz=>'qux'}
{:baz=>'qux'} 'bar' {:bar=>{:baz=>'qux'}}
{:bar=>{:baz=>'qux'}} 'foo' {:foo=>{:bar=>{:baz=>'qux'}}}