我需要帮助F#中的paternmatching。 我想这样做:
let y x =
match x with
| x.Contains("hi") -> "HELLO"
| x.Contains("hello") -> "HI"
| x -> x
但它不起作用。怎么了?
答案 0 :(得分:9)
最简单的方法是在比赛中使用守卫。
let y (x:string) =
match x with
| x when x.Contains("hi") -> "HELLO"
| x when x.Contains("hello") -> "HI"
| x -> x
答案 1 :(得分:7)
包含方法调用的条件只能写入when
后卫,因为pblasucci写道。
如果你想使用一些高级F#功能(例如,如果你需要写很多),那么你可以定义活动模式来检查子串(但如果你只是学习F#,不要担心这个) :
let (|Contains|_|) (what:string) (str:string) =
if str.Contains(what) then Some(str) else None
然后你可以编写类似的东西(有趣的是,你也可以使用嵌套模式检查多个单词,但同样的东西可以使用&
模式编写):
match "hello world" with
| Contains "hello" (Contains "world" str) ->
printfn "%s contains both hello and world!" str
| Contains "hello" str ->
printfn "%s contains only hello!" str
| _ -> ()
答案 2 :(得分:5)
我认为我对前一个问题的回答here可能会帮助您更好地理解模式匹配。
然而,对于你想要做的事情,我可能会坚持使用简单的if / then / else表达式:
let y x =
if x.Contains("hi") then "HELLO"
elif x.Contains("hello") then "HI"
else x
创建一个特殊的Contains
活动模式,如@Tomas Petricek节目也是一个选项,但我发现如果我真的要做一些严肃的字符串模式匹配,那么我只是坚持一对忠实的正则表达式活跃模式:
open System.Text.RegularExpressions
///Match the pattern using a cached interpreted Regex
let (|InterpretedMatch|_|) pattern input =
if input = null then None
else
let m = Regex.Match(input, pattern)
if m.Success then Some [for x in m.Groups -> x]
else None
///Match the pattern using a cached compiled Regex
let (|CompiledMatch|_|) pattern input =
if input = null then None
else
let m = Regex.Match(input, pattern, RegexOptions.Compiled)
if m.Success then Some [for x in m.Groups -> x]
else None
对于这个问题,请像这样使用它们:
let y = function // shorthand for let y x = match x with ...
| CompiledMatch @"hi" _ -> "HELLO"
| CompiledMatch @"hello" _ -> "HI"
| x -> x
我喜欢这个,因为它很容易涵盖Contains,StartsWith,EndsWith,Equals等等:
let y = function
| CompiledMatch @"^hi$" _ -> "Equals"
| CompiledMatch @"^hi" _ -> "StartsWith"
| CompiledMatch @"hi$" _ -> "EndsWith"
| CompiledMatch @"leadinghiending" _ -> "Beyond"
| CompiledMatch @"hi" _ -> "Contains"
| x -> x
(请注意,由@引入的文字字符串实际上并不需要任何这些正则表达式示例,但作为习惯问题,我总是使用它们,因为您经常需要它们而不是正则表达式。)< / p>