我在rails页面上的ruby非常慢。它显示一个分层的,无序的列表。它很慢,因为它是通过递归SQL调用构建列表,这开始是愚蠢的。我已经弄清楚如何让SQL给我层次结构。现在我可以通过单个SQL调用获取所需的信息,但是我在构建生成的HTML时遇到了问题。
这是我的SQL返回的内容。每行是不同的记录,两列'id'和'path'。我可以通过row.path.split
轻松分解不同的项目,以获得['A', 'E', 'F']
之类的内容。我只是无法找出管理列表的开始和结束标记的最佳方法。
ID | PATH
01. Root | Root
02. A | Root A
03. B | Root B
04. C | Root B C
05. D | Root B D
06. E | Root A E
07. F | Root A E F
08. G | Root B D G
09. H | Root B C H
10. I | Root B D I
11. J | Root B D G J
12. F | Root B C H F
13. K | Root B D I K
14. L | Root B D I L
15. F | Root B D I L F
我需要无序列表看起来像这样:
答案 0 :(得分:1)
首先,如果数据很大,我建议简化查询以仅返回带有叶数据的行。您的示例数据中只有5个,其中包含您需要的所有信息。
在任何一种情况下,此代码都会生成所需的html:
#!/usr/bin/env ruby
$h = Hash.new
DATA.each do |path| # replace this line with the SQL query
hash = $h
path.split(' ').each do |e|
if hash.has_key?(e)
hash = hash[e]
else
hash = hash[e] = Hash.new
end
end
end
def hash_to_string( h )
return if h.empty?
list_items = h.map { |k,v| "<li>#{k}#{hash_to_string(v)}</li>\n" }
return "\n<ul>\n#{list_items.join}</ul>";
end
puts hash_to_string( $h )
__END__
Root
Root A
Root B
Root B C
Root B D
Root A E
Root A E F
Root B D G
Root B C H
Root B D I
Root B D G J
Root B C H F
Root B D I K
Root B D I L
Root B D I L F
我建议先直接运行此脚本,看它是否会生成预期的html。然后调整它以符合您的需求;主要是DATA.each ...
行。
答案 1 :(得分:1)
Hash构建的递归版本,DATA
与@Matt的答案完全相同,并且结果哈希也是相同的,因此hash_to_string(h)
将起作用。
class Hash
def merge_path path
return if path == []
first, rest = path.first, path[1..-1]
self[first] ||= {}
self[first].merge_path rest
end
end
hash = {}
DATA.lines.map(&:split).each { |path| hash.merge_path path }
通常,在重新打开和扩展core和stdlib类时应该小心。