ruby - 为较大哈希中的每个嵌套哈希添加深度键

ruby - adding keys for depth to each nested hash inside larger hash

我正在尝试编写一种方法,将嵌套散列作为输入,return使用添加的“深度”键进行散列。所以,例如:

hash = { 
  a: 1,
  b: 2, 
  c: { d: { e: 3 } }
}

会 return:

{
  a: 1,
  b: 2,
  c: {
    d: {
      e: 3,
      depth: 2
    },
    depth: 1
  },
  depth: 0
}

这是我想出的一些代码,它适用于这种情况,或任何其他深度不超过 2 的哈希,但我以错误的方式处理它。我正在尝试弄清楚如何让它适用于任何深度。

def depth(hash)
  hash.values.to_a.map!{|elem| if elem.class==Hash; elem.values.to_a.map!{|el| el.class==Hash ? el[:depth] = 2 : elem}; elem[:depth] = 1; else; elem; end}
  hash[:depth] = 0
  p hash
end

您可以假设输入是哈希。谢谢:-)

如果我明白了,这是一个递归选项。

给定哈希(我增加了更多的深度):

hash_ = { 
  a: 1,
  b: 2, 
  c: { d: { e: 3, f: {g: 4} } }
}

方法如下:

def depth(hash_, deep=1, root=true)
  hash_[:depth] = 0 if root
  root = false
  hash_.each  do |k, v|
    if v.is_a? Hash
      v[:depth] = deep
      depth(v, deep+=1, root)
    end
  end
end

我不太喜欢 root 开关,但这是我想到的第一个想法。

所以你可以调用它并检查结果是否符合预期:

depth(hash_)
#=> {:a=>1, :b=>2, :c=>{:d=>{:e=>3, :f=>{:g=>4, :depth=>3}, :depth=>2}, :depth=>1}, :depth=>0}

如果你想要返回一个添加了深度值的散列,你可以尝试这样的事情:

def desc_hash(hash,depth=0)
  ret = {}
  hash.keys.each do |key|
    if hash[key].instance_of?(Hash)
      ret[key] = desc_hash(hash[key],depth+1)
    else
      ret[key] = hash[key]
    end
  end
  ret[:depth]=depth
  ret
end

以你的哈希为例输出:

2.7.2 :252 > desc_hash(hash)
 => {:a=>1, :b=>2, :c=>{:d=>{:e=>3, :depth=>2}, :depth=>1}, :depth=>0}

这是一个递归例程,它通过任何子哈希将深度传递给自身。

与现有答案相似,但可能更地道

def add_depth(hash, depth = 0)
  hash
    .transform_values { |v| v.is_a?(Hash) ? add_depth(v, depth + 1) : v }
    .merge(depth: depth)
end

它基本上和其他的一样,但是将新哈希的创建和迭代委托给 ruby 核心,可以说是更优化 虚拟机可以更好地优化

在这种情况下,我会使用递归解决方案,但管理自己的堆栈的优点是不会命中 SystemStackError (stack level too deep)

管理您自己的堆栈确实会使事情变得更加复杂,但如果您的散列嵌套得非常深,那么这些努力可能是值得的。

def depth(hash)
  with_depth = hash.merge({ depth: 0 })
  stack = [with_depth]

  while hash = stack.shift # or .pop
    hash.each_key do |key|
      next unless hash[key].is_a?(Hash)
      hash[key] = hash[key].merge({ depth: hash[:depth] + 1 })
      stack << hash[key]
    end
  end

  with_depth
end