2009-02-20 48 views
2

我试着写在F#中的字符串处理函数,它看起来像这样:简单的办法

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

我的模式对几个要素匹配表达式是有点难看(整个'-' :: '-' :: '>'东西)。有什么办法可以让它变得更好吗?另外,如果我要处理大量文本,我的工作效率如何?还是有另一种方式?

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

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

附注 - 我会使用过程而不是过程 - 命名空间冲突或程序员混淆的风险太大。看到这个问题:http://stackoverflow.com/questions/526930/f-naming-convention – Benjol 2009-02-23 08:27:29

+0

感谢您的指针 - 将记住这一点。 – 2009-02-23 14:34:35

+0

`警告FS0046:标识符'进程'保留供F#将来使用` – 2010-08-06 11:02:11

回答

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 
    | [] -> [] 
2

我想你应该避免使用列表<字符>和使用字符串和如String.Replace,String.Contains等System.String和System.StringBuilder将更好地处理文本比列表< char>。

2

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

0

This question可能会给你提供另一种解决问题的方法的想法 - 使用列表<>包含行,但在每行中使用String函数。

3

有没有什么办法让它更好吗?

肯定的:

let process (s: string) = s.Replace("-->", "&rarr;") 

而且,我在做什么有效的,如果我是来处理大量的文本?

不,这是令人难以置信的低效率。分配和垃圾收集非常昂贵,你为每个单个角色都这样做。

或者还有另外一种方法吗?

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