views:

68

answers:

4

Hello.

I need to transform ["a", "b", "c", "d"] to {:a => {:b => {:c => "d" }}} ?

Any ideas ?

Thanks

+1  A: 

I like it:

class Array
  def to_weird_hash
    length == 1 ? first : { first.to_sym => last(length - 1).to_weird_hash }
  end
end

["a", "b", "c", "d"].to_weird_hash

What do you think?

jordinl
What version of ruby is this valid for?
Steve Weet
it's ruby-1.8.7
jordinl
OK. I'm getting undefined method `from` in both 1.8.7 and 1.9.2
Steve Weet
that's weird...
jordinl
I'm doing it now with irb and it's not working, before I did it in script/console. Apparently the method Array#from doesn't exist... :S
jordinl
Nice solution. I'm doing it in rails, so it is working.
retro
Sounds like it is a ROR Monkeypatch.
Steve Weet
yeah, too bad...
jordinl
+4  A: 

funny

ruby-1.8.7-p174 > ["a", "b", "c", "d"].reverse.inject{|hash,item| {item.to_sym => hash}}
 => {:a=>{:b=>{:c=>"d"}}}
hellvinz
I took the liberty of simplifying your code.
Marc-André Lafortune
thanks! i didn't know that inject had this nice feature
hellvinz
+1  A: 

If you need to do it for exactly 4 elements, it's easy enought to just write it out (and quite readable too)

>> A=["a", "b", "c", "d"]
=> ["a", "b", "c", "d"]
>> {A[0].to_sym => {A[1].to_sym => {A[2].to_sym => A[3]}}}
=> {:a=>{:b=>{:c=>"d"}}}

Otherwise, this will work for variable length arrays

>> ["a", "b", "c", "d"].reverse.inject(){|a,e|{e.to_sym => a}}
=> {:a=>{:b=>{:c=>"d"}}}
>> ["a", "b", "c", "d", "e", "f"].reverse.inject(){|a,e|{e.to_sym => a}}
=> {:a=>{:b=>{:c=>{:d=>{:e=>"f"}}}}}
gnibbler
I need it with more than one element.
retro
@retro, not sure what you mean by more than one element. I added a way to do it with variable length arrays
gnibbler
I meant I have more than one element in input array. Also nice solution.
retro
A: 

I figured it out with help on IRC.

x = {}; a[0..-3].inject(x) { |h,k| h[k.to_sym] = {} }[a[-2].to_sym] = a[-1]; x

Second way with recursive (better)

def nest(a)
  if a.size == 2
    { a[0] => a[1] }
  else
    { a[0] => nest(a[1..-1]) }
  end
end
retro