Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set a Ruby hash given a "key path" of arbitrary length?

Tags:

ruby

hash

Given:

h = {foo: {bar: 1}}

How to set bar if you don't know how many keys you have?

For example: keys = [:foo, :bar]

h[keys[0]][keys[1]] = :ok

But what if keys can be of arbitrary length and h is of arbitrary depth?

like image 209
B Seven Avatar asked Nov 16 '25 10:11

B Seven


1 Answers

If you're using Ruby 2.3+ then you can use dig thusly:

h.dig(*keys[0..-2])[keys.last] = :ok

dig follows a path through the hash and returns what it finds. But dig won't copy what it finds so you get the same reference that is in h. keys[0..-2] grabs all but the last element of keys so h.dig(*keys[0..-2]) gives you the {bar: 1} Hash from inside h, then you can modify it in-place with a simple assignment.

You could also say:

*head, tail = keys
h.dig(*head)[tail] = :ok

if that's clearer to you than [0..-2].

If you don't have dig then you can do things like:

*head, tail = keys
head.inject(h) { |m, k| m[k] }[tail] = :ok

Of course, if you're not certain that the path specified by keys exists then you'll need to throw in a some nil checks and decide how you should handle keys that don't specify a path into h.

like image 154
mu is too short Avatar answered Nov 18 '25 20:11

mu is too short



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!