根据数组生成文件列表

时间:2009-04-17 12:34:15

标签: ruby-on-rails ruby list acts-as-tree

我尝试了一些事情,但本周我觉得我的大脑正在度假,我需要完成这件事......所以我希望有人可以帮助我。

我需要根据保存到数据库中的哈希创建文件列表。看起来像这样:

['file1', 'dir1/file2', 'dir1/subdir1/file3']

输出应该是这样的:

      
  • file1的   
  • DIR1
  •   
          
    • file2的
    •     
    • 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”。

有人有另外一个提示如何添加这个吗?

3 个答案:

答案 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