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
我正在尝试编写一种方法,将嵌套散列作为输入,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