2010-09-15 55 views
49

我想匹配f#中字符串的开头。不知道我是否必须把它们当作一个字符列表或什么。任何建议,将不胜感激。f中字符串开头的模式匹配#

这里是什么,我试图做

let text = "The brown fox.." 

match text with 
| "The"::_ -> true 
| "If"::_ -> true 
| _ -> false 

所以,我想看看绳子,比赛开始一个伪代码版本。请注意,我在上面列出的字符串列表中不匹配,作为我尝试做的本质的一个想法。

回答

84

参数化active patterns来救援!

let (|Prefix|_|) (p:string) (s:string) = 
    if s.StartsWith(p) then 
     Some(s.Substring(p.Length)) 
    else 
     None 

match "Hello world" with 
| Prefix "The" rest -> printfn "Started with 'The', rest is %s" rest 
| Prefix "Hello" rest -> printfn "Started with 'Hello', rest is %s" rest 
| _ -> printfn "neither" 
+0

+1。我们希望学习的主动模式的一个很好的例子! – 2010-09-15 23:45:47

+1

这个答案有一个可爱的应用组合主动模式字符串匹配:http://stackoverflow.com/questions/3686199/f-pattern-composition/3686555#3686555 – 2010-09-16 00:52:52

+0

这个答案是太棒了,但我必须承认我flummoxed 。匹配表达式中的“休息”值来自哪里? – 2015-11-29 20:44:40

12

是的,如果您想使用匹配表达式,您必须将它们视为字符列表。

let text = "The brown fox.." |> Seq.toList 

然后你可以用一根火柴的表达,但你将不得不使用字符(元素的列表中的类型),对每个字母:

match text with 
| 'T'::'h'::'e'::_ -> true 
| 'I'::'f'::_ -> true 
| _ -> false 

只需用变换字符串

由于布赖恩建议参数化主动模式更好,有一些有用的模式here(去页面的结尾)。

+0

虽然我使用主动模式更喜欢Brian的答案,我不知道,如果可能的前缀是只有少数这一个可能更有效,不久。对此有何见解? – 2010-09-16 09:40:14

+0

您必须创建一个临时数组和一个F#列表,因此可能会有很多会增加GC压力的对象。这根本不是最佳的。你最好使用两个'StartsWith'或'StartsWith' + AP。 – Stringer 2010-09-16 12:13:12

+3

由于字符串已经是'char seq',你可以使用'Seq.toList'。 – YotaXP 2010-09-16 16:41:16

11

你也可以使用保护上的图案:

match text with 
| txt when txt.StartsWith("The") -> true 
| txt when txt.StartsWith("If") -> true 
| _ -> false 
+0

这也是一个很好的例子,特别是如果你想在包含=和参数的开关上部分匹配。 – octopusgrabbus 2017-06-28 17:19:46