From: Glenn Ritz Date: 2010-03-01T00:56:31+09:00 Subject: Re: Iterate over hash of nested hashes Robert Klemme wrote: > 2010/2/24 Xavier Noria : >>>> >>> {'en' => {'A' => Fixnum, 'B' => {'C' => Fixnum, 'D' => String }} >> � �newh[k] = v.is_a?(Hash) ? classify_values(v) : v.class >> �end >> �newh >> end >> >> p classify_values({'en' => {'A' => 1, 'B' => {'C' => 3, 'D' => 'four' }}}) > > I would do it a tad differently: > > def classify(o) > case o > when Hash > h = {} > o.each {|k,v| h[k] = classify(v)} > h > else > o.class > end > end > > Advantage is that you can stuff anything in the method while your > variant requires the argument to be a Hash. The difference may seem > subtle but if you add more collection types for special treatment, > you'll will notice a difference in effort to implement it. I can > simply do > > def classify(o) > case o > when Hash > h = {} > o.each {|k,v| h[k] = classify(v)} > h > when Array > o.map {|v| classify(v)} > else > o.class > end > end > > while you need to do a more complicated code change. > > Kind regards > > robert Thanks, this is very helpful. I am trying to adapt this a bit, but with no luck so far. What I'd like to do is to start with a hash and have the above code be additive. In other words, if I have the following code: h0 = {} h1 = {'en' => {'A' => 5, 'B' => { 'C' => 'xxx', 'D' => { 'E' => 4 }}}} h2 = {'en' => {'F' => 'yyy'}} I'd like to be able to call the classify method like this: puts h0.classify(h1).classify(h2).inspect And get the following result: {'en' => {'A' => Fixnum, 'B' => { 'C' => String, 'D' => { 'E' => Fixnum }}, 'F' => String }} So I figured it would be something like this: class Hash def classify(o) case o when Hash h = self o.each {|k,v| h[k] = classify(v)} h when Array o.map {|v| classify(v)} else o.class end end end But this is probably wrong in a few ways. Any suggestions would be appreciated. Thanks. -- Posted via http://www.ruby-forum.com/.