#ruby #parsing #markdown
#ruby #синтаксический анализ #markdown
Вопрос:
Следующее — лучшее, что я смог придумать;
def markdownparser(markdown)
if markdown.match("#")
arr = markdown.split("")
i = 0
while arr[i] != " "
if arr[i] == "#"
i = 1
end
end
final = markdown[(i 1)..(markdown.size i)]
return "<h" i.to_s ">" final "</h" i.to_s ">"
else
return markdown
end
end
puts markdownparser(" smaller header")
Простая функция синтаксического анализа markdown:
- принимает одну строку markdown
- преобразует его в соответствующий HTML-тег заголовка
Заголовки обозначаются (1-6) хэшами, за которыми следует пробел, а затем текст. Количество хэшей определяет уровень заголовка в выходных данных HTML.
- Содержимое заголовка должно располагаться только после начальных хэштегов плюс пробел.
- Недопустимые заголовки должны просто возвращаться как markdown, который был получен без какого-либо перевода.
- Пробелы перед и после содержимого заголовка и хэштега (ов) должны быть проигнорированы в результирующем выводе
Как я могу еще больше сократить временные затраты?
Заранее большое спасибо
Ответ №1:
Замените явные циклы стандартными методами
Вы выполняете ряд действий в циклах, поэтому я бы избегал этого, если у вас нет очень специфического варианта использования, чтобы не использовать оптимизированные методы Ruby. Существуют встроенные методы ядра или стандартной библиотеки для выполнения таких действий, как подсчет вхождений или замена текста, поэтому я бы использовал их, когда это возможно. Если скорость действительно имеет значение, я бы также выбрал интерполяцию строк, а не конкатенацию с строкой # , где каждое подвыражение создает новую промежуточную строку.
Один из способов реализовать это было бы следующим:
md_str = <<~'EOF'
# Header 1
Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor
incidunt ut labore et dolore magna aliqua.
## Header 2
Etiam habebis sem dicantur magna mollis euismod.
####### Invalid Header with 7 "#" Characters
^^^^^^^ Too many characters to be valid.
EOF
# helper method to count header characters
def header_level str
stramp;.count "#"
end
# replace markdown headers with html headers;
# escape hash in regex so it won't be treated as interpolation;
# block form required for proper handling of match variables
md_str.gsub!(/^(#{1,6})s (.*)$/) { |_| "<h#{header_level $1}>#{$2}</h>" }
puts md_str
Это использует String#count для подсчета количества #
символов в вашей строке, вместо того, чтобы перебирать ее в цикле. Строка#gsub вызывает #header_level только в строках, которые начинаются с символа заголовка.
Предостережения
- Очевидно, что это не обрабатывает «подчеркнутые» заголовки, но это не было частью вашего вопроса.
- Обработка файлов в режиме «Перебор» по сравнению с построчной обработкой требует различных компромиссов, но может быть сложно выполнить сложный синтаксический анализ без строк контекста.
- Ничто не заменит сравнительный анализ, чтобы проверить, действительно ли данный фрагмент кода быстрее или нет.
- Этот подход не устраняет итерацию как таковую. Он просто по возможности перегружает итерацию методам, которые выполняются со скоростью C.
Комментарии:
1. Спасибо, Тодд! Ваше решение сработало для меня, и IDE тестируемого сайта была принята после настройки регулярных выражений для соответствия всем тестовым случаям