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