数组中的Ruby深度嵌套哈希

时间:2019-03-06 16:09:57

标签: 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)

也无效

4 个答案:

答案 0 :(得分:3)

send的作用是调用 a 方法,该方法只有一个,带有零个或多个参数。它不能一次调用多个方法。您的示例在这里:

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作为块参数传递”,如带有签名的方法一样:

initialize(&block)

&block代表该方法的块(如果已给出),如:

Hash.new { |h,k| h[k] = { } }

在更基本的实现中。

-> h, k { ... }部分传统上写为:

lambda { |h, k| ... }

那可能更容易识别。

答案 1 :(得分:2)

[:a, :b, :c, :d, :e].reverse_each.inject{|h, k| {k => h}}
# => {:a=>{:b=>{:c=>{:d=>:e}}}}

答案 2 :(得分:1)

ID  Name    Amount  Comments
1   n1      421762  Hello
2   n2      5810    Bye

答案 3 :(得分:1)

array = [*:a..:e]
array[0..-2].reverse.reduce(array[-1]) { |b, a| { a => b } }
#  {:a=>{:b=>{:c=>{:d=>:e}}}}