F#中列表开始的模式匹配更简单的方法

时间:2009-02-20 19:27:28

标签: parsing list f# pattern-matching

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

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

我的模式匹配表达式对几个元素有点难看(整个'-' :: '-' :: '>'事物)。有没有办法让它变得更好?另外,如果我要处理大型文本,我的效率是多少?或者还有另一种方式吗?

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

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

5 个答案:

答案 0 :(得分: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  
  | [] -> []

答案 1 :(得分:3)

  

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

不确定

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

另外,如果我要处理大型文本,我的效率是多少?

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

  

还是有另一种方式吗?

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

答案 2 :(得分:2)

我认为你应该避免使用list< char>并使用字符串和String.Replace,String.Contains等。对于操作文本,System.String和System.StringBuilder比列表< char>更好。

答案 3 :(得分:2)

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

答案 4 :(得分:0)

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