假设我有一个任意深度嵌套的哈希h
:
h = {
:foo => { :bar => 1 },
:baz => 10,
:quux => { :swozz => {:muux => 1000}, :grimel => 200 }
# ...
}
让我们说我的课程C
定义为:
class C
attr_accessor :dict
end
如何替换h
中的所有嵌套值,以便它们现在是C
个实例,并将dict
属性设置为该值?例如,在上面的例子中,我希望有类似的东西:
h = {
:foo => <C @dict={:bar => 1}>,
:baz => 10,
:quux => <C @dict={:swozz => <C @dict={:muux => 1000}>, :grimel => 200}>
# ...
}
其中<C @dict = ...>
代表C
个@dict = ...
个实例。 (请注意,只要您达到未嵌套的值,就会停止将其包装在C
个实例中。)
答案 0 :(得分:1)
def convert_hash(h)
h.keys.each do |k|
if h[k].is_a? Hash
c = C.new
c.dict = convert_hash(h[k])
h[k] = c
end
end
h
end
如果我们覆盖inspect
中的C
以提供更友好的输出,请执行以下操作:
def inspect
"<C @dict=#{dict.inspect}>"
end
然后使用您的示例h
运行,这会给出:
puts convert_hash(h).inspect
{:baz=>10, :quux=><C @dict={:grimel=>200,
:swozz=><C @dict={:muux=>1000}>}>, :foo=><C @dict={:bar=>1}>}
此外,如果您向initialize
添加C
方法以设置dict
:
def initialize(d=nil)
self.dict = d
end
然后你可以将convert_hash
中间的3行减少到h[k] = C.new(convert_hash_h[k])
答案 1 :(得分:1)
class C
attr_accessor :dict
def initialize(dict)
self.dict = dict
end
end
class Object
def convert_to_dict
C.new(self)
end
end
class Hash
def convert_to_dict
Hash[map {|k, v| [k, v.convert_to_dict] }]
end
end
p h.convert_to_dict
# => {
# => :foo => {
# => :bar => #<C:0x13adc18 @dict=1>
# => },
# => :baz => #<C:0x13adba0 @dict=10>,
# => :quux => {
# => :swozz => {
# => :muux => #<C:0x13adac8 @dict=1000>
# => },
# => :grimel => #<C:0x13ada50 @dict=200>
# => }
# => }