来自数组的 Ruby 深层嵌套哈希

标签 ruby recursion

我需要转换这个数组:

[: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/

相关文章:

ruby - 如何让 Mechanize 自动将正文转换为 UTF8?

ruby-on-rails - Ruby 哈希通过比较值合并

ruby - 在 Mechanize (Ruby) 中跳过大页面

ruby - Ruby 中的递归斐波那契数列

php - 带有递归的 ArrayCollection::forAll

linux - 如何递归查找并列出具有子目录和时间的目录中的最新修改文件

ruby - 迭代嵌套哈希并修改值

algorithm - 递归 Levinshtein 算法的下界

php - 将键值对的 PHP 数组转换为分层嵌套树结构

"foo.nil? ? nil : foo.to_i"的 Ruby 习语?