Hash 对象如下所示,它同时具有数组和哈希值,但嵌套总是发生在“children”数组的值处:
a = {"id" => "1", "children" => [{"id"=>"11", "children"=>[{"id"=>"111"}]}, {"id"=>"12", "children"=>[{"id"=>"121", "children"=>[{"id"=>"1211"}]}, {"id"=>"122"}]}]}
a.max_depth = 3
The following (non-recursive) instance method Hash#depth
returns the desired measure of depth. I've add a puts
statement to display the intermediate calculations.
class Hash
def depth
arr = values
d = 0
loop do
arr = arr.flatten.select { |e| e.is_a? Hash }
break d if arr.empty?
d += 1
arr = arr.map(&:values)
puts "d = #{d}, arr = #{arr}"
end
end
end
a.depth
d = 1, arr = [["11", [{"id"=>"111"}]], ["12", [{"id"=>"121", "children"=>
[{"id"=>"1211"}]}, {"id"=>"122"}]]]
d = 2, arr = [["111"], ["121", [{"id"=>"1211"}]], ["122"]]
d = 3, arr = [["1211"]]
#=> 3
如果您特别想找到“孩子”键的深度,您可以使用这种方法:
class Hash
def max_depth
max_depth = 1
depth_func = ->(hsh, cur_depth) do
max_depth = cur_depth if cur_depth > max_depth
hsh["children"].to_a.each{|h| depth_func.call(h, cur_depth+1)}
max_depth
end
depth_func.call(self, 0)
end
end
现在您可以尝试以下代码:
h = { "id" => "1", "children" => [{"id"=>"11", "children"=>[{"id"=>"111"}]},
{"id"=>"12", "children"=>[{"id"=>"121", "children"=>[{"id"=>"1211"}]},
{"id"=>"122"}]}]}
h.max_depth # 3
这将找到任何嵌套哈希的深度,还遍历数组并为其分配零深度。
class Hash
def max_depth
1 + values.map do |val|
if val.respond_to?(:max_depth)
val.max_depth
elsif val.respond_to?(:max)
val.max { |elt| elt.max_depth }
else
0
end
end.max
end
end
这应该适用于您的情况:
def array_traverse(array, depth)
array.each do |i|
if i.class == Array
depth = array_traverse(i, depth)
elsif i.class == Hash
depth = hash_traverse(i, depth)
end
end
return depth
end
def hash_traverse(hash, depth)
hash.keys().each do |i|
depth += 1 if i == 'children' and hash[i].length > 1
if hash[i].class == Array
depth = array_traverse(hash[i], depth)
elsif hash[i].class == Hash
depth = hash_traverse(hash[i], depth)
end
end
return depth
end
puts hash_traverse(a, 1)