From: Zhi-Qiang Lei Date: 2010-11-05T23:58:22+09:00 Subject: Re: Convert Array to nested Hash On Oct 24, 2010, at 7:07 PM, Robert Klemme wrote: > 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/ > I'm sorry to bring this old topic out. But there is a question make me confused. 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}} Is the tuple (k1, k2, v) in block arguments an array? What's the meaning of () in block arguments? Thanks. Best regards, Zhi-Qiang Lei zhiqiang.lei@gmail.com