我尝试了一些事情,但本周我觉得我的大脑正在度假,我需要完成这件事......所以我希望有人可以帮助我。
我需要根据保存到数据库中的哈希创建文件列表。看起来像这样:
['file1', 'dir1/file2', 'dir1/subdir1/file3']
输出应该是这样的:
在html中,最好像这样(用js扩展它以折叠和多选)
<ul>
<li>file1
<li>dir1</li>
<ul>
<li>file2</li>
<li>subdir1</li>
<ul>
<li>file3</li>
</ul>
</ul>
</ul>
我正在使用Ruby on Rails并尝试在RJS模板中实现这一点。但这并不重要。你也可以帮我一些详细的伪代码。
有人知道如何解决这个问题吗?
修改
感谢所有人提供这些解决方案。列表工作,我将其扩展为可折叠的解决方案,以显示/隐藏目录内容。我仍然有一个问题:代码的目的是在同步条目后面的复选框中有完整的文件路径。基于sris的解决方案,我只能读取当前文件和它的子,但不能读取根目录的整个路径。为了更好地理解:
目前:
[x] dir1
[x] dir2
[x] file1
给了我
显示相同值的复选框,例如[x] file1的“file1”。但我需要的是一个完整的路径,例如[x] file1的“dir1 / dir2 / file1”。
有人有另外一个提示如何添加这个吗?
答案 0 :(得分:3)
这是一个可以用于灵感的快速实现。此实现忽略输入数组中文件的顺序。
我已根据您的要求更新了解决方案以保存整个路径。
dirs = ['file1', 'dir1/file2', 'dir1/subdir1/file3', 'dir1/subdir1/file5']
tree = {}
dirs.each do |path|
current = tree
path.split("/").inject("") do |sub_path,dir|
sub_path = File.join(sub_path, dir)
current[sub_path] ||= {}
current = current[sub_path]
sub_path
end
end
def print_tree(prefix, node)
puts "#{prefix}<ul>"
node.each_pair do |path, subtree|
puts "#{prefix} <li>[#{path[1..-1]}] #{File.basename(path)}</li>"
print_tree(prefix + " ", subtree) unless subtree.empty?
end
puts "#{prefix}</ul>"
end
print_tree "", tree
此代码将像您的示例一样生成正确的缩进HTML。但由于Ruby中的Hashes(1.8.6)未被订购,因此无法保证文件的顺序。
产生的输出将如下所示:
<ul>
<li>[dir1] dir1</li>
<ul>
<li>[dir1/subdir1] subdir1</li>
<ul>
<li>[dir1/subdir1/file3] file3</li>
<li>[dir1/subdir1/file5] file5</li>
</ul>
<li>[dir1/file2] file2</li>
</ul>
<li>[file1] file1</li>
</ul>
我希望这可以作为如何获得路径和文件名的示例。
答案 1 :(得分:1)
想想树。
# setup phase
for each pathname p in list
do
add_path_to_tree(p)
od
walk tree depth first, emitting HTML
add_path_to_tree
是递归的
given pathname p
parse p into first_element, rest
# that is, "foo/bar/baz" becomes "foo", "bar/baz"
add first_element to tree
add_path_to_tree(rest)
我将保留树(列表列表)的最佳数据结构(列表列表)作为练习。
答案 2 :(得分:1)
扩展sris的答案,如果你真的想要排序所有内容并在目录前列出文件,你可以使用这样的东西:
def files_first_traverse(prefix, node = {})
puts "#{prefix}<ul>"
node_list = node.sort
node_list.each do |base, subtree|
puts "#{prefix} <li>#{base}</li>" if subtree.empty?
end
node_list.each do |base, subtree|
next if subtree.empty?
puts "#{prefix} <li>#{base}</li>"
files_first_traverse(prefix + ' ', subtree)
end
puts '#{prefix}</ul>'
end