我是一位对学习F#感兴趣的C#开发人员。我有一个非常简单的问题:在第一次出现数字或逗号时将字符串分成两部分。显然,天真的实现是:
let parts = text.Split([| ','; '0'; '1'; '2'; '3'; '4'; '5'; '6'; '7'; '8'; '9' |], 2)
但是,这看起来不太实用,并且性能可能很差。我想知道,在F#中还有更好的方法吗?我当时在看Active patterns,但不知道如何正确使用它们。还是应该使用“好旧的”正则表达式?
答案 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])