Parsing 针对F中列表开头的模式匹配的更简单方法#

Parsing 针对F中列表开头的模式匹配的更简单方法#,parsing,list,f#,pattern-matching,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

我正在尝试用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 Process html =
  match html with
  | '-' :: '-' :: '>' :: tail -> ("→" |> List.of_seq) @ Process tail
  | head :: tail -> head :: Process tail
  | [] -> []
match html with
| "-->" :: tail -> 

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

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

可能有助于您了解解决问题的另一种方法-使用列表包含行,但是在每一行中使用字符串函数。

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

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  
  | [] -> []
有没有办法让它变得更好

当然可以:

另外,如果我要处理大文本,我所做的是有效的吗

不,它的效率非常低。分配和垃圾收集是非常昂贵的,而且您对每个字符都这样做

还是有别的办法


尝试
替换
成员。如果这不起作用,请尝试使用正则表达式。如果这不起作用,请编写一个lexer(例如,使用
fslex
)。最终,要提高效率,您需要的是一个状态机处理一个字符流,并通过就地突变输出其结果。

旁注-我本应该使用进程而不是进程-太多命名空间冲突或程序员混乱的风险。请看这个问题:谢谢你的指针-请记住这一点。
警告FS0046:标识符“process”保留给F#
你的代码片段中包含的F#我实际上不懂:)请帮我回到书中来!谢谢好吧,我发现这样做很难,效率很低。然而,在C#中使用System.String和诸如此类的工具来完成这项工作也很乏味。最后,我编写了一个DSL,生成了一些真正邪恶的C++代码来解决这个问题。是的,这就是真正的男人所做的。