以递归方式将哈希转换为 OpenStruct [英] Convert Hash to OpenStruct recursively
问题描述
鉴于我有这个哈希:
h = { a: 'a', b: 'b', c: { d: 'd', e: 'e'} }
然后我转换为 OpenStruct:
And I convert to OpenStruct:
o = OpenStruct.new(h)
=> #<OpenStruct a="a", b="b", c={:d=>"d", :e=>"e"}>
o.a
=> "a"
o.b
=> "b"
o.c
=> {:d=>"d", :e=>"e"}
2.1.2 :006 > o.c.d
NoMethodError: undefined method `d' for {:d=>"d", :e=>"e"}:Hash
我希望所有嵌套的键也是方法.所以我可以像这样访问 d
:
I want all the nested keys to be methods as well. So I can access d
as such:
o.c.d
=> "d"
我怎样才能做到这一点?
How can I achieve this?
推荐答案
我个人使用 recursive-open-struct
gem - 那么它就像 RecursiveOpenStruct.new(<nested_hash>)
personally I use the recursive-open-struct
gem - it's then as simple as RecursiveOpenStruct.new(<nested_hash>)
但为了递归练习,我将向您展示一个新的解决方案:
But for the sake of recursion practice, I'll show you a fresh solution:
require 'ostruct'
def to_recursive_ostruct(hash)
OpenStruct.new(hash.each_with_object({}) do |(key, val), memo|
memo[key] = val.is_a?(Hash) ? to_recursive_ostruct(val) : val
end)
end
puts to_recursive_ostruct(a: { b: 1}).a.b
# => 1
编辑
这比基于 JSON 的解决方案更好的原因是,当您转换为 JSON 时,您可能会丢失一些数据.例如,如果您将 Time 对象转换为 JSON,然后对其进行解析,它将是一个字符串.还有很多其他的例子:
the reason this is better than the JSON-based solutions is because you can lose some data when you convert to JSON. For example if you convert a Time object to JSON and then parse it, it will be a string. There are many other examples of this:
class Foo; end
JSON.parse({obj: Foo.new}.to_json)["obj"]
# => "#<Foo:0x00007fc8720198b0>"
是的……不是很有用.你已经完全失去了对实际实例的引用.
yeah ... not super useful. You've completely lost your reference to the actual instance.
这篇关于以递归方式将哈希转换为 OpenStruct的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!