wang kai
wang kai

Reputation: 1747

How to avoid writing regex match twice?

I have this code:

let main argv = 
let x="b"
match x with
| _ when Regex.Match(x,"a").Success=true->
    let a=Regex.Match(x,"a")
    Console.WriteLine(a.Groups.[0])
| _ when Regex.Match(x,"b").Success=true->
    let b=Regex.Match(x,"b")
    Console.WriteLine(b.Groups.[0])

I have to write Regex.Match(x,"a") and Regex.Match(x,"b") twice in the above code. Is there some way to write it only once?

Upvotes: 4

Views: 95

Answers (2)

Be Brave Be Like Ukraine
Be Brave Be Like Ukraine

Reputation: 7735

Go for active patterns:

let (|Match|_|) pattern input =
    let m = Regex.Match(input, pattern, RegexOptions.Singleline)
    if m.Success 
        then Some (m.Groups.[0])
        else None
// and use it:
match x with
| Match @"a text" a ->
    printfn "found a: %s" a
| Match @"b text" b ->
    printfn "found b: %s" b

You can go even further and make an active pattern that supports its own number of parsed values:

let (|Regex|_|) pattern input =
    let m = Regex.Match(input, pattern, RegexOptions.Singleline)
    if m.Success
        // List.tail is needed to skip the m.Groups.[0] that returns the entire parsed scope
        then [ for g in m.Groups -> g.Value ] |> List.tail |> Some
        else None

match x with
| Regex @"a (\w+)\s(\w+)" [ a1; a2 ] ->
    printfn "found A value: %s and %s" a1 a2
| Regex @"b (\w+)\s(\w+)\s(\w+)" [ b1; b2; b3 ] ->
    printfn "found B value: %s and %s and %s" b1 b2 b3

// this will be able to parse the following:
// "a foo bar"     ==> a1="foo" and a2="bar"
// "b foo bar baz" ==> b1="foo", b2="bar", and b3="baz"

Upvotes: 7

Tim Biegeleisen
Tim Biegeleisen

Reputation: 522254

You can try using a single pattern with an alternation:

let main argv = 
let x = "b"
match x with
| _ when Regex.Match(x, "a|b").Success = true ->
    let m = Regex.Match(x, "a|b")
    Console.WriteLine(m.Groups.[0])

Upvotes: 0

Related Questions