4

I don't really know if the title is correct, but the question is quite simple:

I have a value and a key.

The key is as follows:

"one.two.three"

Now, how can I set this hash:

params['one']['two']['three'] = value

2
  • This is definitely a duplicate; look hard on the site and you'll find more answers. Commented Jan 26, 2012 at 11:59
  • 3
    Your comment would be useful if it included a link. Commented Jan 27, 2012 at 2:19

3 Answers 3

1

You can try to do it with this code:

keys = "one.two.three".split '.' # => ["one", "two", "three"]
params = {}; value = 1; i = 0;  # i is an index of processed keys array element
keys.reduce(params) { |hash, key|
    hash[key] = if (i += 1) == keys.length
      value # assign value to the last key in keys array
    else
      hash[key] || {} # initialize hash if it is not initialized yet (won't loose already initialized hashes)
    end
}
puts params # {"one"=>{"two"=>{"three"=>1}}}
Sign up to request clarification or add additional context in comments.

2 Comments

Looks good, was hoping for a one liner, but this will work.. Thanks!
@Tim. No need for one-liners, just create an abstraction Hash#set_from_path(path, value) written with good, clear, maintenable code.
1

Use recursion:

def make_hash(keys)
  keys.empty? ? 1 : { keys.shift => make_hash(keys) }
end

puts make_hash("one.two.three".split '.')
# => {"one"=>{"two"=>{"three"=>1}}}

1 Comment

this is ok to create a new hash, but I thought the OP wanted to update an existing hash...
1

You can use the inject method:

key = "one.two.three"
value = 5

arr = key.split(".").reverse
arr[1..-1].inject({arr[0] => value}){ |memo, i| {i => memo} }
# => {"one"=>{"two"=>{"three"=>5}}}

5 Comments

So can I make this a one liner like so: hash = key.split(".").reverse[1..-1].inject({arr[0] => value}){ |memo, i| {i => memo}} ?
+Tim, arr is not defined in your one liner
"one.two.three".split('.').reverse.inject(5) { |x, y| { y => x } } outputs => {"one"=>{"two"=>{"three"=>5}}}
That looks very nice, but how can I do it on an existing hash ?
This is so elegant, it should be the accepted answer!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.