我需要转换这个数组:
[:a, :b, :c, :d, :e]
进入这个散列:
{:a=>{:b=>{:c=>{:d=>:e}}}}
不幸的是,我错过了大脑的递归叶。我找到了 BottomlessHash
# http://firedev.com/posts/2015/bottomless-ruby-hash/
class BottomlessHash < Hash
def initialize
super &-> h, k { h[k] = self.class.new }
end
end
虽然我正在努力理解“pretzel stab”,但如果您明确地将其写出来,它就可以解决问题,
bhash = BottomlessHash.new
bhash[:a][:b][:c][:d] = :e
bhash # => {:a=>{:b=>{:c=>{:d=>:e}}}}
但是我想不出一种以编程方式传递任意值的方法。
store
不起作用,send("[:a][:b][:c][:d]=", :e)
也不起作用
最佳答案
send
所做的是调用一个 方法,只有一个方法,带有零个或多个参数。它不能一次调用多个方法。你的例子在这里:
send("[:a][:b][:c][:d]=", :e)
这试图调用一个名为 [:a][:b][:b][:d]=
的方法,它不存在,所以 send
失败。
现在这段实际的 Ruby 代码:
x[:a][:b][:c][:d] = :e
被 Ruby 解释为:
x.send(:[], :a).send(:[], :b).send(:[], :c).send(:[]=, :d, :e)
这只是一种非常冗长、丑陋的方式来执行原始代码所做的事情。这里的关键是每个 [...]
部分代表一个方法调用,它返回一些东西,然后下一部分根据它进行评估,或者链接。
现在是原始部分,这个椒盐脆饼:
super &-> h, k { h[k] = self.class.new }
&
的意思是“将此 Proc 作为 block 参数传递”,对于具有签名的方法:
initialize(&block)
其中 &block
表示该方法的 block (如果给定的话),如:
Hash.new { |h,k| h[k] = { } }
在更基本的实现中。
-> h, k { ... }
部分传统上写成:
lambda { |h, k| ... }
这可能更容易辨认。
关于来自数组的 Ruby 深层嵌套哈希,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55027514/