ruby-on-rails - 在 Ruby 中通过递归嵌套哈希

标签 ruby-on-rails ruby recursion

我一直在尝试在 Ruby 中以编程方式制作嵌套的默认哈希,基本上是 Ruby 的简写:

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

我想将其扩展到所需的多个级别。我做了以下功能:

def nested_hash(level, default={})
   return default if level == 0
   return Hash.new{ |h,k| h[k] = nested_hash(level - 1, default) }
end

看起来它工作正常但是我在创建多个 key 时遇到了以下问题

h = nested_hash(1)
h[0][1] = [1, 2, 3] # h is {0=>{1=>[1, 2, 3]}}
h[2] # should give a new Hash, but returns {1=>[1, 2, 3]}
h # {0=>{1=>[1, 2, 3]}, 2=>{1=>[1, 2, 3]}} 

为什么函数的默认值变了,变成了之前设置的值?

编辑

我找到了一个有效的解决方案:

def nested_hash(level, default={})
    return Hash.new{ |h,k| h[k] = default } if level <= 1
    Hash.new{ |h,k| h[k] = nested_hash(level - 1, default) }
end

没关系,这不会以类似的方式工作:

h = nested_hash(1)
h[0][1] = [1, 2, 3]
h[2][0] # nil
h # {0=>{1=>[1, 2, 3]}, 2=>{1=>[1, 2, 3]}}

我仍然对为什么在 key 之间共享原始默认值感到困惑。

最佳答案

出于好奇:

hash =
  Hash.new do |h, k|
    h[k] = h.dup.clear.extend(Module.new do
      define_method(:level, ->{ h.level - 1 })
    end).tap { |this| raise "🔥" if this.level <= 0 }
  end.extend(Module.new { define_method(:level, ->{ 5 }) })

#⇒ {}

hash["0"]["1"]["2"]["3"]
#⇒ {}
hash["0"]["1"]["2"]["3"]["4"]
#⇒ RuntimeError: "🔥"

或者,作为一个函数:

def nhash lvl
  Hash.new do |h, k|
    h[k] = h.dup.clear.extend(Module.new do
      define_method(:level, ->{ h.level - 1 })
    end).tap { |this| raise "🔥" if this.level < 0 }
  end.extend(Module.new { define_method(:level, ->{ lvl }) })
end

导致:

✎ h = nhash 2
#⇒ {}
✎ h[0][1] = [1, 2, 3]
#⇒ [1, 2, 3]
✎ h[2][0]
#⇒ {}
✎ h[2][0][5]
#⇒ RuntimeError: 🔥

如有必要,可能会重置默认过程而不是提高。

这种方法的唯一缺点是,在尝试调用高于允许的级别时,将创建所有中间空哈希。 可以通过定义方法、累积路径(而不是简单地返回级别)和在提升之前删除空 parent 来克服。

关于ruby-on-rails - 在 Ruby 中通过递归嵌套哈希,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54558485/

相关文章:

ruby-on-rails - 根据登录时的用户角色设计重定向到特定页面

ruby-on-rails - 与 erlang 服务器共享 Rails session

ruby-on-rails - rails 4.0 中为删除操作创建 link_to 的问题

ruby - 在 Ruby 1.9.3 中使用 %x 调用 pwd 是否存在任何已知问题?

ruby 为什么0 || 1 是 0

php - 递归完成后,如何清除 PHP 中的静态变量?

c# - 递归目录遍历/树消耗大量内存

javascript - 在 rails 中使用 javascript_pack_tag 导致 EOFError

无法将 C 程序转换为 Ruby

Python celery worker_main "RuntimeError: maximum recursion depth exceeded"