Ruby - 以递归方式散列方法

时间:2015-02-07 18:03:04

标签: ruby

我有哈希散列,我需要把它变成方法,其中键是方法名称,值是方法返回的值,但是额外要求如果值也是哈希值,返回整个值。

例如:

hash = {:a => 1, :b => 2, :c => { :a => 1, :b => 2, :c => 3} }
hash.c.a  #=> 1
hash.c    #=> { :a => 1, :b => 2, :c => 3}

我怎么能这样做?帮助赞赏。

3 个答案:

答案 0 :(得分:3)

您可以使用OpenStruct来创建这样的数据结构。例如:

require 'ostruct'
s = OpenStruct.new(a: 1, b: 2, c: OpenStruct.new(a: 1, b: 2, c: 3))
s.c.a # => 1
s.c   # => #<OpenStruct a=1, b=2, c=3>

答案 1 :(得分:0)

另一种选择是使用Hashie。 Hashie是一组类似哈希的扩展。其中包括您可以直接访问字段的哈希 - 具体参见Mash选项:

mash = Hashie :: Mash.new(:a =&gt; 1,:b =&gt; 2,:c =&gt; Hashie :: Mash.new(:a =&gt; 1,:b =&gt; 2,:c =&gt; 3))

答案 2 :(得分:0)

由于您的接收器是哈希,因此您必须在类Hash上定义方法:

def makem(h)
  h.each do |k,v|
    case v
    when Hash
      Hash.instance_eval { define_method(k.to_s) { v } }
      v.each { |kk,vv| Hash.instance_eval { define_method(kk.to_s) { vv } } }
    end
  end
end

让我们试一试:

h = {:a => 1, :b => 2, :c => { :a => 1, :b => 2, :d => 3 } }

makem(h)
Hash.instance_methods(false).select { |m| m.size == 1 }
  #=> [:c, :a, :b, :d] 
h.c
  #=> {:a=>1, :b=>2, :d=>3} 
h.c.a
  #=> 1 
h.c.b
  #=> 2 
h.c.d
  #=> 3 

在您的示例中,您有:

:c => { :a => 1, :b => 2, :c => 3}

如果你想要一个返回上面哈希的方法c,你显然不能定义另一个返回3的同名方法。

您可能希望重新考虑定义这些方法的可取性。也许在你的类中构造诸如def m(hash, key)之类的方法会更有用。