以递归方式将哈希转换为 OpenStruct [英] Convert Hash to OpenStruct recursively

查看:30
本文介绍了以递归方式将哈希转换为 OpenStruct的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

鉴于我有这个哈希:

 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆