Более простой способ сопоставления с началом списка в F # - PullRequest
2 голосов
/ 20 февраля 2009

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

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

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

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

match html with
| "-->" :: tail -> 

Ответы [ 5 ]

5 голосов
/ 26 марта 2009

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

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  
  | [] -> []
3 голосов
/ 06 августа 2010

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

Sure:

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

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

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

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

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

2 голосов
/ 20 февраля 2009

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

2 голосов
/ 20 февраля 2009

Я думаю, что вам следует избегать использования списка и использования строк и, например, String.Replace, String.Contains и т. Д. System.String и System.StringBuilder будут намного лучше работать с текстом, чем список .

0 голосов
/ 23 февраля 2009

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

...