2013-09-06 2 views
0

У меня очень медленная рубина на странице рельсов. Он отображает иерархический, неупорядоченный список. Это было медленным, потому что он создавал список через рекурсивные SQL-вызовы, что было глупо для начала. Я выяснил, как заставить SQL предоставить мне иерархию. Теперь, когда я могу получить необходимую информацию через один вызов SQL, у меня возникают проблемы с созданием полученного HTML.Лучший способ построения иерархического списка из строк строк

Это то, что возвращает мой SQL. Каждая строка представляет собой другую запись, два столбца «id» и «путь». Я могу легко разбить разные предметы, выполнив row.path.split, чтобы получить что-то вроде ['A', 'E', 'F']. Я просто не могу понять, как лучше всего управлять открытием и закрытием тегов списка.

 ID | PATH 
01. Root | Root 
02. A  | Root A 
03. B  | Root B 
04. C  | Root B C 
05. D  | Root B D 
06. E  | Root A E 
07. F  | Root A E F 
08. G  | Root B D G 
09. H  | Root B C H 
10. I  | Root B D I 
11. J  | Root B D G J 
12. F  | Root B C H F 
13. K  | Root B D I K 
14. L  | Root B D I L 
15. F  | Root B D I L F 

И мне нужно неупорядоченный список, чтобы выглядеть примерно так:

format of unordered list

Source html of the above screenshot

+0

Ваша ситуация не ясна. Я полагаю, что '[" A "," E "]' указан в '[" A "]', с '' A ''опущен. Как это отличает случаи, когда существует "[" A "]' и случаи, когда это не так? Другими словами, существует ли существование "[" A "," E "," F "]' 'существование" ["A", "E"] ', что в свою очередь влечет за собой существование" ["A «]'? Если это так, то ваши данные являются излишними. – sawa

+0

@sawa - SQL возвращает каждый узел и его путь. Однако в списке узлы объединяются, поэтому каждый узел появляется только один раз. '' И '' E "' оба появляются в списке, но только один раз. Нет необходимости указывать '' A "' как узел, так и лист – lightswitch05

+0

Вы, похоже, не правильно задали мой вопрос. Пожалуйста, прочитайте его еще раз. Чтобы слить '[" A "," E "]' с '[" A "]', вам нужно иметь '[" A "]'. Я спрашиваю, имеет ли место, что всякий раз, когда у вас есть '[" A "," E "]', вы также имеете '[" A "]'. – sawa

ответ

1

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

В любом случае, этот код создает нужный HTML:

#!/usr/bin/env ruby 

$h = Hash.new 
DATA.each do |path| # replace this line with the SQL query 
    hash = $h 
    path.split(' ').each do |e| 
    if hash.has_key?(e) 
     hash = hash[e] 
    else 
     hash = hash[e] = Hash.new 
    end 
    end 
end 

def hash_to_string(h) 
    return if h.empty? 
    list_items = h.map { |k,v| "<li>#{k}#{hash_to_string(v)}</li>\n" } 
    return "\n<ul>\n#{list_items.join}</ul>"; 
end 

puts hash_to_string($h) 

__END__ 
Root 
Root A 
Root B 
Root B C 
Root B D 
Root A E 
Root A E F 
Root B D G 
Root B C H 
Root B D I 
Root B D G J 
Root B C H F 
Root B D I K 
Root B D I L 
Root B D I L F 

Я предлагаю продолжить этот сценарий первого непосредственно, как это, чтобы увидеть, что он генерирует ожидаемый HTML. Затем настройте его, чтобы он соответствовал вашим потребностям; главным образом линия DATA.each ....

1

Рекурсивная версия здания хеширования, DATA принимается точно так же, как в ответе @ Мэтта, а также в результате хеша будет то же самое, поэтому hash_to_string(h) будет работать так же.

class Hash 
    def merge_path path 
    return if path == [] 
    first, rest = path.first, path[1..-1] 
    self[first] ||= {} 
    self[first].merge_path rest 
    end 
end 

hash = {} 
DATA.lines.map(&:split).each { |path| hash.merge_path path } 

Как правило, вы должны быть осторожны при повторном открытии и расширении классов ядра и класса stdlib.

Смежные вопросы