Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby inject recursion?

Tags:

ruby

recursion

The goal is to start with ['a','b','c'] and end up with {'a'=>{'b'=>{'c'=>{}}}}

so, getting my bearings, i did this:

['a','b','c'].inject({}){|h,v| h.update(v => {})}
# => {"a"=>{}, "b"=>{}, "c"=>{}} 

and then figured, if i actually pass on the result hash, it will recurse and nest, but:

['a','b','c'].inject({}){|h,v| h.update(v => {}); h[v]}
# => {} 

Why is this? Any idea how to achieve the desired result in an elegant one-liner?

like image 255
Matt Humphrey Avatar asked Dec 09 '25 01:12

Matt Humphrey


2 Answers

['a','b','c'].reverse.inject({}) {|r,v| {v=>r}}

Or in other words:

Construct a hash with the key being the first array element ('c' after it is reversed), and the seed (an empty hash) as the value. At each step construct a new hash where the key is the next value from the array, and the value is the hash returned from the previous step.

Here are the results after each iteration of inject:

r={}, v='c' returns {'c'=>{}}

r={'c'=>{}}, v='b' returns {'b'=>{'c'=>{}}}

r={'b'=>{'c'=>{}}}, v='a' returns {'a'=>{'b'=>{'c'=>{}}}}

like image 124
zetetic Avatar answered Dec 10 '25 19:12

zetetic


Zetetic already gave you a working solution, but here's the reason why yours didn't work:

['a','b','c'].inject({}){|h,v| h.update(v => {}); h[v]}

This will indeed create the hash {'a'=>{'b'=>{'c'=>{}}}} however, inject will not return that hash, it returns the result of the last call to the block and that 's {} because h will be the hash created for the last element, i.e. {'c' => {}} and thus h[v] will be {}.

To see that the hash you want actually does get created, just not returned, you can store the hash you pass in in a variable first, like this:

hash = {}
['a','b','c'].inject(hash){|h,v| h.update(v => {}); h[v]}

This way the inject will still return {}, but hash will now contain the hash {'a'=>{'b'=>{'c'=>{}}}}. That being said zetetic's solution is better as it's clearer what's going on. Mutating the accumulator in inject is usually confusing and more trouble than it's worth.

like image 39
sepp2k Avatar answered Dec 10 '25 19:12

sepp2k



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!