2

私はいくつかのことを試しましたが、今週は私の脳が休日を過ごしているように感じ、これを完了する必要があります..誰かが私を助けてくれることを願っています.

データベースに保存されているハッシュに基づいてファイルリストを作成する必要があります。has は次のようになります。

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

出力は次のようになります。

  • ファイル1
  • dir1
    • ファイル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 テンプレートでこれを達成しようとしています。しかし、これは実際には問題ではありません。また、詳細な疑似コードについても教えてください。

誰かがこれを解決する方法を知っていますか?


編集

これらのソリューションを提供してくれた皆さんに感謝します。リストは機能します。ディレクトリの内容を表示/非表示にする折りたたみ式ソリューションに拡張しました。まだ問題が 1 つあります。コードは、同期用のエントリの背後にあるチェックボックスに完全なファイル パスを設定することを目的としています。sris のソリューションに基づいて、現在のファイルとそのサブのみを読み取ることができますが、ルートからのパス全体を読み取ることはできません。理解を深めるために:

現在:

[x] dir1
    [x] dir2
        [x] file1

私にくれます

テキストが表示されるのと同じ値のチェックボックス (例: [x] file1 の場合は "file1")。しかし、必要なのはフル パスです。たとえば、[x] file1 の場合は "dir1/dir2/file1" です。

誰かがこれを追加する方法について別のヒントを持っていますか?

4

3 に答える 3

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

これが、パスとファイル名の両方を取得する方法の例として役立つことを願っています。

于 2009-04-17T13:04:18.827 に答える
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
于 2009-04-17T13:19:51.037 に答える
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)

演習として、ツリー (リストのリスト) の最適なデータ構造 (リストのリスト) を残します。

于 2009-04-17T12:50:18.893 に答える