Ruby 嵌套哈希动态获取
我在尝试使用密钥更新嵌套哈希时遇到问题。
我的嵌套哈希是这样的:
main_hash = {
"Energy"=>
{"name"=>"Energy", "uri"=>"energy",
"children"=>
{"Renewable Energy"=>{"name"=>"Renewable Energy", "uri"=>"energy/renewable_energy"}}}
,
"Farming"=>
{"name"=>"Farming", "uri"=>"farming",
"children"=>
{"Organic Gas"=>
{"name"=>"Organic Gas", "uri"=>"farming/organic_gas"
"children" =>
{"Gas Oil"=>{"name"=>"Gas Oil", "uri"=>"farming/organic_gas/gas_oil"}}
}}}}
我想做的是更新哈希中的一个项目(例如,我想向“有机气体”添加另一个子项)。我知道我可以做到这一点:
main_hash["Farming"]["children"]["Organic Gas"]["children"].merge!(another_hash)
问题是我需要动态获取它,因为它可能会嵌套得很深。
因此,为了达到所需的水平,我会这样做(其工作原理如上所述)。
main_hash.send(:fetch, "Farming").send(:fetch, "children").send(:fetch, "Organic Gas").send(:fetch, "children")
如果我可以像下面这样动态调用“发送”方法(显然它不起作用),那就太好了。
main_hash.send(:try, 'send(:fetch, "Farming").send(:fetch, "children").send(:fetch, "Organic Gas").send(:fetch, "children")')
我希望它能明确我想要实现的目标。我已经浏览了 Ruby Hash 的所有内置函数,但找不到适合我需要的函数。
任何帮助将不胜感激。
干杯。
I have an issue trying to update a nested Hash using a key.
The nested hash I have is like this:
main_hash = {
"Energy"=>
{"name"=>"Energy", "uri"=>"energy",
"children"=>
{"Renewable Energy"=>{"name"=>"Renewable Energy", "uri"=>"energy/renewable_energy"}}}
,
"Farming"=>
{"name"=>"Farming", "uri"=>"farming",
"children"=>
{"Organic Gas"=>
{"name"=>"Organic Gas", "uri"=>"farming/organic_gas"
"children" =>
{"Gas Oil"=>{"name"=>"Gas Oil", "uri"=>"farming/organic_gas/gas_oil"}}
}}}}
What I would like to do is to update an item from the hash (e.g., I want to add another child to "Organic Gas"). I know I can do this:
main_hash["Farming"]["children"]["Organic Gas"]["children"].merge!(another_hash)
The problem is I need to get that dynamically as it can get quite deeply nested.
So to get to the desired level, I would do this (which does work as above).
main_hash.send(:fetch, "Farming").send(:fetch, "children").send(:fetch, "Organic Gas").send(:fetch, "children")
It would really be great if I could call "send" method dynamically like below (obviously it won't work).
main_hash.send(:try, 'send(:fetch, "Farming").send(:fetch, "children").send(:fetch, "Organic Gas").send(:fetch, "children")')
I hope it makes it clear what I want to achieve. I have gone through all Ruby Hash's built in function and I can't get the one suited for my need.
Any help would be greatly appreciated.
Cheers.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我不确定哈希是否真的是最好的数据结构。你试图用它来表示一棵树,这很好,但如果你只是明确地将它变成一棵树,它可能会更清晰一些:(
我只是从我之前制作的树结构中借用了这些枚举器 -
each_leaf
方法也可能有帮助,您可以检查该类是否不是Tree
而不是leaf?
返回true 如果您有一个可以包含其他内容的树结构对象,如字符串)。
然后你可以这样做:
我认为这只是为工作找到正确的数据结构的一个例子。即使树方法的效率稍低,它也会更清楚发生的情况,并且可能会导致动态代码中的错误更少。
如果问题是您不想修改原始树,只想复制,然后重新定义:
这样,您保留原始树,但返回添加了额外子项的新树。
I'm not sure a Hash is really the best data structure here. You're trying to use it to represent a tree, which is fine and all, but it might be a bit clearer if you just explicitly made it a tree:
(I just borrowed those enumerators from a tree structure I'd made before - the
each_leaf
method might be helpful too, and you can check for the class not beingTree
instead ofleaf?
returningtrue
if you had a tree structure that could contain other objects, like strings).Then you could do:
I think this is just a case of finding the right data structure for the job. Even if the tree method were a bit less efficient, it's clearer what's going on, and will probably lead to fewer bugs in your dynamic code down the track.
If the problem is that you don't want the original tree to be modified, only copied, then just redefine:
That way, you retain the original tree but return a new tree with the extra child added.
要回答最初的问题,您可以使用 XKeys gem 遍历动态路径,如下所示:
我还建议使用 :children 而不是 'children' 以避免出现大量重复字符串。
To answer the original question, you can use the XKeys gem to traverse a dynamic path as follows:
I would also recommend using :children instead of 'children' to avoid having huge numbers of duplicate strings.