Hash オブジェクトは次のようになります。配列とハッシュ値の両方がありますが、入れ子は常に「子」配列の値で発生します。
a = {"id" => "1", "children" => [{"id"=>"11", "children"=>[{"id"=>"111"}]}, {"id"=>"12", "children"=>[{"id"=>"121", "children"=>[{"id"=>"1211"}]}, {"id"=>"122"}]}]}
a.max_depth = 3
次の (非再帰的な) インスタンス メソッドHash#depth
は、必要な深さの測定値を返します。puts
中間計算を表示するステートメントを追加しました。
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
これはあなたのケースでうまくいくはずです:
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)