Написать анализатор markdown тегов HTML заголовка в Ruby

#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 только в строках, которые начинаются с символа заголовка.

Предостережения

  1. Очевидно, что это не обрабатывает «подчеркнутые» заголовки, но это не было частью вашего вопроса.
  2. Обработка файлов в режиме «Перебор» по сравнению с построчной обработкой требует различных компромиссов, но может быть сложно выполнить сложный синтаксический анализ без строк контекста.
  3. Ничто не заменит сравнительный анализ, чтобы проверить, действительно ли данный фрагмент кода быстрее или нет.
  4. Этот подход не устраняет итерацию как таковую. Он просто по возможности перегружает итерацию методам, которые выполняются со скоростью C.

Комментарии:

1. Спасибо, Тодд! Ваше решение сработало для меня, и IDE тестируемого сайта была принята после настройки регулярных выражений для соответствия всем тестовым случаям