我正在尝试定义一个函数,它可以以树格式打印出任何哈希值。该函数将执行以下操作:
来自
{"parent1"=>
{"child1" => { "grandchild1" => 1,
"grandchild2" => 2},
"child2" => { "grandchild3" => 3,
"grandchild4" => 4}}
}
到
parent1:
child1:
grandchild1:1
grandchild2:2
child2:
grandchild3:3
grandchild4:4
到目前为止,这是我的代码:
def readprop(foo)
level = ''
if foo.is_a?(Hash)
foo.each_key {|key| if foo[key].nil? == false
puts level + key + ":"
level += " "
readprop(foo[key])
end
}
else
puts level + foo
level = level[0,level.length - 2]
end
end
它会给我一个糟糕的格式:
parent1:
child1:
grandchild1:
1
grandchild2:
2
child2:
grandchild3:
3
grandchild4:
4
答案 0 :(得分:4)
你快到了。解决它的一种方法是使level
成为递归函数参数的一部分。 x
是问题中的哈希值。
简单的递归版本:
def print_hash(h,spaces=4,level=0)
h.each do |key,val|
format = "#{' '*spaces*level}#{key}: "
if val.is_a? Hash
puts format
print_hash(val,spaces,level+1)
else
puts format + val.to_s
end
end
end
print_hash(x)
#parent1:
# child1:
# grandchild1: 1
# grandchild2: 2
# child2:
# grandchild3: 3
# grandchild4: 4
在这种情况下,您还可以将其转换为YAML(如上面的评论所述)
require 'YAML'
puts x.to_yaml
#---
#parent1:
# child1:
# grandchild1: 1
# grandchild2: 2
# child2:
# grandchild3: 3
# grandchild4: 4
答案 1 :(得分:2)
我会使用递归,但还有另一种方式可能会让一些人感兴趣。下面我使用了一台漂亮的打印机",awesome-print来完成部分格式化(特别是缩进),将结果保存到字符串中,然后应用了几个gsub's
到字符串,将结果按到所需的格式。
假设您的哈希值如下:
h = { "parent1"=>
{ "child1" => { "grandchild11" => 1,
"grandchild12" => { "great grandchild121" => 3 } },
"child2" => { "grandchild21" => { "great grandchild211" =>
{ "great great grandchild2111" => 4 } },
"grandchild22" => 2 }
}
}
然后我们可以执行以下操作。
require 'awesome_print'
puts str = h.awesome_inspect(indent: -5, index: false, plain: true).
gsub(/^\s*(?:{|},?)\s*\n|[\"{}]/, '').
gsub(/\s*=>\s/, ':')
打印
parent1:
child1:
grandchild11:1,
grandchild12:
great grandchild121:3
child2:
grandchild21:
great grandchild211:
great great grandchild2111:4
grandchild22:2
步骤:
str = h.awesome_inspect(indent: -5, index: false, plain: true)
puts str
打印
{
"parent1" => {
"child1" => {
"grandchild11" => 1,
"grandchild12" => {
"great grandchild121" => 3
}
},
"child2" => {
"grandchild21" => {
"great grandchild211" => {
"great great grandchild2111" => 4
}
},
"grandchild22" => 2
}
}
}
s1 = str.gsub(/^\s*(?:{|},?)\s*\n|[\"{}]/, '')
puts s1
打印
parent1 =>
child1 =>
grandchild11 => 1,
grandchild12 =>
great grandchild121 => 3
child2 =>
grandchild21 =>
great grandchild211 =>
great great grandchild2111 => 4
grandchild22 => 2
s2 = s1.gsub(/\s*=>\s/, ':')
puts s2
打印上面的结果。
答案 2 :(得分:1)
不完全符合您的要求,但我会提交此答案,因为我认为您可能认为它有用:
require 'yaml'
hash = {"parent1"=> {"child1" => { "grandchild1" => 1,"grandchild2" => 2},
"child2" => { "grandchild3" => 3,"grandchild4" => 4}}}
puts hash.to_yaml
打印:
---
parent1:
child1:
grandchild1: 1
grandchild2: 2
child2:
grandchild3: 3
grandchild4: 4
答案 3 :(得分:0)
假设我们有
#$ mkdir -p foo/bar
#$ mkdir -p baz/boo/bee
#$ mkdir -p baz/goo
我们可以
{
"baz"=>{
"boo"=>{
"bee"=>{}},
"goo"=>{}},
"foo"=>{
"bar"=>{}}}
我们可以如下遍历树。所以,这是一种基于磁盘上的目录树制作哈希的方法:
Dir.glob('**/*'). # get all files below current dir
select{|f|
File.directory?(f) # only directories we need
}.map{|path|
path.split '/' # split to parts
}.inject({}){|acc, path| # start with empty hash
path.inject(acc) do |acc2,dir| # for each path part, create a child of current node
acc2[dir] ||= {} # and pass it as new current node
end
acc
}
感谢MladenJablanović在这个概念的另一个答案中。