【问题标题】:Generate a file list based on an array基于数组生成文件列表
【发布时间】:2010-10-20 02:26:36
【问题描述】:

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

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

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

输出应该是这样的:

  • 文件1
  • 目录1
    • 文件2
    • 子目录1
      • 文件3

在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”。

有人有其他提示如何添加这个吗?

【问题讨论】:

  • 你写的是hash,但是粘贴的代码是Array,是什么?
  • 噢,对不起,把事情搞砸了。这是一个像我写的数组。感谢您提及 sris。

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


【解决方案1】:

这是一个快速实现,您可以从中获得灵感。此实现不考虑输入数组中文件的顺序。

我已根据您的需要更新了解决方案以保存整个路径。

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 (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>

我希望这是一个示例,说明如何获取路径和文件名。

【讨论】:

  • 这几乎就是我要发布的内容。
  • 好的,实现了这个解决方案,但还有一个问题:我需要完整的文件路径作为复选框的值(每个 li 前缀都是一个复选框)。这里我只获取文件。
  • 我已更新示例以删除路径变量名称的重复使用。希望这能回答你的问题
【解决方案2】:

扩展 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

【讨论】:

  • 我不想把原始代码弄得太乱,但这是一个很好的补充!
  • 没有必要按顺序排列,但感谢您的补充:-)
【解决方案3】:

思考树。

  # 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)

我将把树(列表列表)的最佳数据结构(列表列表)作为练习。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-08
    • 2012-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多