Создать список файлов на основе массива - PullRequest
2 голосов
/ 17 апреля 2009

Я попробовал несколько вещей, но на этой неделе я чувствую, что у моего мозга каникулы, и мне нужно закончить это ... поэтому я надеюсь, что кто-то может мне помочь.

Мне нужно создать список файлов на основе хэша, который сохраняется в базе данных. Это выглядит так:

['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

дает мне

флажок с тем же значением, что и текст, например, «file1» для [x] file1. Но мне нужен полный путь, например, «dir1 / dir2 / file1» для [x] file1.

У кого-нибудь есть еще один совет, как это добавить?

Ответы [ 3 ]

3 голосов
/ 17 апреля 2009

Вот быстрая реализация, которую вы можете использовать для вдохновения. Эта реализация игнорирует порядок файлов во входном массиве.

Я обновил решение, чтобы сохранить весь путь в соответствии с вашими требованиями.

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>

Надеюсь, это послужит примером того, как вы можете получить как путь, так и имя файла.

1 голос
/ 17 апреля 2009

Расширяя ответ 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
1 голос
/ 17 апреля 2009

Думай о дереве.

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

Я оставлю оптимальную структуру данных (список списков) для дерева (список списков) в качестве упражнения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...