为较大散列中的每个嵌套散列添加深度键



我正在尝试编写一个方法,该方法将嵌套散列作为输入,并返回添加了"深度"的散列;钥匙。例如:

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

将返回:

{
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

可以假设输入是一个哈希值。谢谢:-)

与现有答案相似,但可能更符合习惯用法

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内核,可以被认为是更优的可以被虚拟机更好地优化。

如果您希望返回一个带有深度值的散列,您可以尝试这样做:

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}

这是一个递归例程,它将深度传递给自身,并带有任何子哈希值。

在这种情况下,我将使用递归解决方案,但是管理你自己的堆栈的好处是你不会碰到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

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

给定哈希值(我增加了一个深度):

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}

最新更新