开发者

Ruby inject 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?


['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'=>{}}}}


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜