Robert Klemme wrote:
> 2010/2/24 Xavier Noria <fxn / hashref.com>:
>>>>
>>> {'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/.