我正试图这样解析一个yaml文件:
a:
a1:
a2:
b:
b1:
b11:
b2:
我得到一个这样的杂烩:
{"a"=>{"a1"=>nil, "a2"=>nil}, "b"=>{"b1"=>{"b11"=>nil}, "b2"=>nil}}
我想把它变成一个列表:
%ul
%li a
%ul
%li a1
%li a2
%li b
%ul
%li b1
%ul
%li b11
%li b2
我在努力寻找最有效的方法不管散列有多深
最后我这样做了:
KeyWords = %w(url)
# Convert a multilevel hash into haml multilevel tree
# Special KeyWords
# url : item url
def hash_to_haml(hash, url = nil)
haml_tag(:ul) do
hash.each do |key, value|
unless KeyWords.include?(key)
url = get_url(key, value)
haml_tag(:li) do
haml_tag(:a, :href => url ) do
haml_concat(key)
end
hash_to_haml(value) if value.is_a?(Hash) && !value.empty?
end
end
end
end
end
private
def get_url(key, hash)
# TODO: get full url from hash
if hash.nil?
"/#{key}"
else
hash.include?("url") ? hash.delete("url") : "/#{key}"
end
end
现在也准备分析选项了。
最佳答案
要输出到纯html,只需在each
块中对同一个函数执行递归调用(或者像我在这里所做的那样将该函数用作each
块):
def hash_to_html key,value
if value.nil?
puts "<li>#{key}</li>"
elsif value.is_a?(Hash)
puts "<li>#{key}"
puts "<ul>"
value.each(&method(:hash_to_html))
puts "</ul></li>"
else
fail "I don't know what to do with a #{value.class}"
end
end
puts "<ul>"
yourhash.each(&method(:hash_to_html))
puts "</ul>"
要输出到您正在使用的任何模板语言(我想是haml),我们需要跟踪缩进,所以事情要复杂一些——我们将使用一个函数,它将缩进深度作为参数,并返回要在每个键/值对上调用的另一个函数使用适当的缩进(递归地)打印该键/值对。(在函数式编程中,以这种方式调用函数被称为“部分应用的函数”,它们通常比ruy更容易定义。)
def hash_to_haml depth
lambda do |key,value|
puts " "*depth + "%li #{key}"
if value.nil?
# do nothing
# (single this case out, so as not to raise an error here)
elsif value.is_a?(Hash)
puts " "*(depth+1) + "%ul"
value.each(&hash_to_haml(depth+2))
else
fail "I don't know what to do with a #{value.class}"
end
end
end
puts "%ul"
yourhash.each(&hash_to_haml(1))