2

我正在尝试在 F# 中编写一个字符串处理函数,如下所示:

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

我对几个元素的模式匹配表达式有点难看(整个'-' :: '-' :: '>'事情)。有没有办法让它变得更好?另外,如果我要处理大文本,我正在做的事情是否有效?还是有其他方法?

澄清:我的意思是,例如,能够写出这样的东西:

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

5 回答 5

5

我同意其他人的观点,即使用字符列表进行严重的字符串操作可能并不理想。但是,如果您想继续使用这种方法,一种接近您所要求的方法的方法是定义一个活动模式。例如:

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  
  | [] -> []
于 2009-03-26T06:34:44.160 回答
3

有没有办法让它变得更好?

当然:

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

另外,如果我要处理大文本,我正在做的事情是否有效?

不,这是非常低效的。分配和垃圾收集是昂贵的,而且你为每个角色都这样做。

还是有其他方法?

试试Replace会员。如果这不起作用,请尝试使用正则表达式。如果这不起作用,请编写一个词法分析器(例如使用fslex)。最终,您想要提高效率的是状态机处理字符流并通过就地变异输出其结果。

于 2010-08-06T10:58:06.023 回答
2

我认为您应该避免使用 list<char> 和使用字符串,例如 String.Replace、String.Contains 等。System.String 和 System.StringBuilder 在处理文本方面会比 list<char> 好得多。

于 2009-02-20T19:56:15.033 回答
2

对于简单的问题,Brian 提到的直接使用 String 和 StringBuilder 可能是最好的方法。对于更复杂的问题,您可能需要查看一些复杂的解析库,例如FParsec for F#。

于 2009-02-20T20:26:40.717 回答
0

这个问题可能有助于为您提供解决问题的另一种方法的想法 - 使用 list<> 包含行,但在每行中使用 String 函数。

于 2009-02-23T08:29:27.780 回答