第一次出现数字或逗号时分割字符串

时间:2020-07-27 07:31:45

标签: f#

我是一位对学习F#感兴趣的C#开发人员。我有一个非常简单的问题:在第一次出现数字或逗号时将字符串分成两部分。显然,天真的实现是:

let parts = text.Split([| ','; '0'; '1'; '2'; '3'; '4'; '5'; '6'; '7'; '8'; '9' |], 2)

但是,这看起来不太实用,并且性能可能很差。我想知道,在F#中还有更好的方法吗?我当时在看Active patterns,但不知道如何正确使用它们。还是应该使用“好旧的”正则表达式?

3 个答案:

答案 0 :(得分:3)

如果标准的.NET库操作没有发生变异,则没有任何功能失常。 Split操作采用一个字符串并返回一个字符串集合,因此它的功能非常完善。

代码的一个问题是,如果字符串中包含多个数字或空格,Split会将字符串分成多个部分,而不是2个部分,因此您可能要使用IndexOf查找第一个拆分字符的索引,然后使用它来拆分字符串。

在这种情况下,我不会使用任何复杂的东西,例如活动模式和正则表达式。以下内容很清楚:

let splitString (s:string) =
  let i = s.IndexOfAny("0123456789 ,".ToCharArray())
  if i < 0 then None 
  else Some(s.Substring(0, i), s.Substring(i+1))

如果这是更复杂的规则处理系统的一部分,那么有必要使用主动模式,在该系统中,您需要编码10多个这样的规则,但是对于单个功能,简单性是最好的!

答案 1 :(得分:2)

您可以使用ToCharArray方法来获取字符串的char数组,然后使用Array.tryFindIndex函数来查找分隔符,最后使用Substring方法来拆分字符串分为两部分。

代码如下:

let str = "hello,world"
str.ToCharArray ()
|> Array.tryFindIndex (fun ch -> ch = ',' || (ch >= '0' && ch <= '9'))
|> function | Some i -> str.Substring(0, i), str.Substring(i + 1)
            | None -> str, ""

我真的不知道为什么您实际上要在这里使用活动模式。但是,当您有多种方式分隔字符串时,使用活动模式可能会很有用。它可以使代码更具可读性,例如:

// Write some Active Patterns:

let split condition (str: string) =
    str.ToCharArray ()
    |> Array.tryFindIndex condition
    |> Option.map (fun i -> str.Substring(0, i), str.Substring(i + 1))

let (| SeparatedByCommaOrDigits | _ |) str =
    str |> split (fun ch -> ch = ',' || (ch >= '0' && ch <= '9'))
    
let (| SeparatedByDotOrUnderscrore | _ |) str =
    str |> split (fun ch -> ch = '.' || ch = '_')

// The beauty of Active Patterns:

let str = "hel,lo_world"
match str with
| SeparatedByCommaOrDigits (a, b) -> printfn "%s\n%s" a b
| SeparatedByDotOrUnderscrore (a, b) -> printfn "%s\n%s" a b
| _ -> printfn "invalid"

答案 2 :(得分:0)

我将为此使用“旧的”正则表达式:

open System.Text.RegularExpressions

let parts text =
    let a = Regex.Split(text,"[,0-9](.+)")
    if a.Length < 2 then None else Some (a.[0],a.[1])