从路径字符串构建分层列表的最佳方法

时间:2013-09-06 18:21:12

标签: html ruby-on-rails ruby algorithm

我在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

我需要无序列表看起来像这样:

format of unordered list

Source html of the above screenshot

2 个答案:

答案 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类时应该小心。