Более простой способ сопоставления шаблона с началом списка в F#

StackOverflow https://stackoverflow.com/questions/570899

Вопрос

Я пытаюсь написать функцию обработки строк в F #, которая выглядит следующим образом:

let rec Process html =
  match html with
  | '-' :: '-' :: '>' :: tail -> ("→" |> List.of_seq) @ Process tail
  | head :: tail -> head :: Process tail
  | [] -> []

Мое выражение сопоставления с шаблоном для нескольких элементов немного уродливо (весь '-' :: '-' :: '>' вещь).Есть ли какой-нибудь способ сделать это лучше?Кроме того, эффективно ли то, что я делаю, если бы мне приходилось обрабатывать большие тексты?Или есть другой способ?

Разъяснение:я имею в виду, например, возможность написать что-то вроде этого:

match html with
| "-->" :: tail -> 
Это было полезно?

Решение

Я согласен с другими, что использование списка символов для выполнения серьезных манипуляций со строками, вероятно, не идеально.Однако, если вы хотите продолжать использовать этот подход, один из способов получить что-то близкое к тому, о чем вы просите, - это определить активный шаблон.Например:

let rec (|Prefix|_|) s l =
  if s = "" then
    Some(Prefix l)
  else
    match l with
    | c::(Prefix (s.Substring(1)) xs) when c = s.[0] -> Some(Prefix xs)
    | _ -> None

Тогда вы можете использовать его как:

let rec Process html =  
  match html with  
  | Prefix "-->" tail -> ("→" |> List.of_seq) @ Process tail  
  | head :: tail -> head :: Process tail  
  | [] -> []

Другие советы

Есть ли какой-нибудь способ сделать это лучше?

Конечно:

let process (s: string) = s.Replace("-->", "→")

Кроме того, эффективно ли то, что я делаю, если бы мне приходилось обрабатывать большие тексты?

Нет, это невероятно неэффективно.Выделение и сборка мусора обходятся дорого, и вы делаете это для каждого отдельного символа.

Или есть другой способ?

Попробуйте Replace Участник.Если это не сработает, попробуйте использовать регулярное выражение.Если это не сработает, напишите лексер (напримериспользуя fslex).В конечном счете, то, что вам нужно для повышения эффективности, - это конечный автомат, обрабатывающий поток символов и выводящий его результат путем изменения на месте.

Я думаю, вам следует избегать использования списка<char> и использования строк и, напримерСтрока.Заменить, строка.Содержит и т.д.System.Строка и System.StringBuilder будет намного лучше работать с текстом, чем со списком<char>.

Для простых задач, вероятно, лучше всего использовать String и StringBuilder напрямую, как упоминал Брайан.Для более сложных задач вы можете захотеть ознакомиться с какой-нибудь сложной библиотекой синтаксического анализа, такой как Парсек для F#.

Этот вопрос может быть, это поможет вам придумать другой способ решения вашей проблемы - использование списка<> содержать строки, но используя строковые функции внутри каждой строки.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top