From: Robert Klemme Date: 2010-10-24T20:07:19+09:00 Subject: Re: Convert Array to nested Hash On Sun, Oct 24, 2010 at 11:27 AM, Sandor Szuecs wrote: > > On Oct 24, 2010, at 7:25 AM, Zhi-Qiang Lei wrote: > >> Dear All, >> >> I'm seeking a method to convert an array like: >> >> [ >>       ["A", "a", 1] >>       ["A", "b", 2] >>       ["B", "a", 1] >> >> ] >> >> into a hash as follow: >> { >>       {"A" => {"a" => 1, "b" => 2}}, >>       {"B" => {"a" => 1}} >> } >> >> Do you have any idea on this? Thanks in advance. > > I don't think that you really want to add 3 layers of dictionary. > If you really want this, then you think about your abstractions to > get a simpler solution. > >  a = [ >    ["A", "a", 1], >    ["A", "b", 2], >    ["B", "a", 1] >  ] > > def a_to_h(a) >  h={} >  a.map do |nested| >    key = nested.shift >    h[key] ||= {} >    h[key].merge!({ nested.shift => nested.shift }) >  end >  h > end > > irb:0> a_to_h(a) > => {"A"=>{"a"=>1, "b"=>2}, "B"=>{"a"=>1}} Here's another way: irb(main):019:0> [ irb(main):020:1* ["A", "a", 1], irb(main):021:1* ["A", "b", 2], irb(main):022:1* ["B", "a", 1], irb(main):023:1* irb(main):024:1* ].inject({}) do |h,(k1,k2,v)| irb(main):025:1* (h[k1] ||= {})[k2] = v irb(main):026:1> h irb(main):027:1> end => {"A"=>{"a"=>1, "b"=>2}, "B"=>{"a"=>1}} and another one irb(main):028:0> [ irb(main):029:1* ["A", "a", 1], irb(main):030:1* ["A", "b", 2], irb(main):031:1* ["B", "a", 1], irb(main):032:1* irb(main):033:1* ].inject(Hash.new {|h,k| h[k]=Hash.new(&h.default_proc)}) do |h,(k1,k2,v)| irb(main):034:1* h[k1][k2] = v irb(main):035:1> h irb(main):036:1> end => {"A"=>{"a"=>1, "b"=>2}, "B"=>{"a"=>1}} But I totally agree: why build up a strcuture of nested Arrays and then convert it into the nested Hash structure? Is is much more efficient to build up the Hash structure initially. One might even create a Struct for values in the top level Hash. Cheers robert -- remember.guy do |as, often| as.you_can - without end http://blog.rubybestpractices.com/