假设我有这个哈希值:
h = { a: 'a', b: 'b', c: { d: 'd', e: 'e'} }
我转换为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
:
o.c.d
=> "d"
我如何才能做到这一点?
9条答案
按热度按时间zbwhf8kr1#
您可以对
Hash
类进行monkey-patch那么你可以说
请参阅Convert a complex nested hash to an object。
bksxznpy2#
我想出了这个办法:
所以为了让它起作用,我必须做一个额外的步骤:将其转换为json。
j9per5c43#
我个人使用
recursive-open-struct
gem -它就像RecursiveOpenStruct.new(<nested_hash>)
一样简单但为了便于递归练习,我将向您展示一个新的解决方案:
卫行健在这里表现出了轻微的改善https://stackoverflow.com/a/69311716/2981429
另请参见https://stackoverflow.com/a/63264908/2981429,它显示了如何处理数组
这比基于JSON的解决方案更好的原因是,当你转换成JSON时,你可能会丢失一些数据。2例如,如果你把一个Time对象转换成JSON,然后解析它,它将是一个字符串。3还有很多其他的例子:
是的......不是很有用。你已经完全失去了对实际示例的引用。
brccelvz4#
下面是一个递归的解决方案,它可以避免将hash转换为json:
uwopmtnx5#
我的解决方案基于max pleaner's answer,与Xavi's answer类似:
qeeaahzv6#
我的解决方案比@max-pleaner的更干净、更快。
我不知道为什么,但我没有示例化额外的Hash对象:
以下是供您参考的基准:
第一个
qcuzuvrc7#
这里有一种重写初始化器的方法,这样你就可以执行
OpenStruct.new({ a: "b", c: { d: "e", f: ["g", "h", "i"] }})
。此外,当您使用
require 'json'
时,这个类也包含在其中,因此请确保在使用require
后执行此修补程序。xtfmy6hx8#
Basing a conversion on OpenStruct works fine until it doesn't. For instance, none of the other answers here properly handle these simple hashes:
The method below works with those hashes, modifying the input hash rather than returning a new object.
then
Or if your context calls for a more inline call structure:
Alternatively, you could mix it in:
and apply to individual hashes:
Here is a variation for monkey-patching Hash, should you opt to do so:
Comments to other answers expressed a desire to retain class types. This solution accommodates that.
Whatever solution you choose, I recommend testing with this hash:
people = { person1: { display: { first: 'John' } }, person2: { display: { last: 'Jingleheimer' } } }
gtlvzcf89#
如果您可以对Hash类进行monkey-patching,那么您可以:
理想情况下,我们应该能够使用Refinement,而不是假装这样,但是由于某种原因,我不明白它对each_pair方法不起作用(而且,不幸的是,Refinement仍然非常有限)