如何在 F# 中检查字符串是否仅包含字母

4

我有一个字符串,它只应包含字母。为了检查这一点,我编写了以下代码:

let isCorrectString(str:string) = 
 let isInRange x = (x > 64 && x < 91 ) || (x > 96 && x < 123) || x = 32
 not (str.Any(fun ch -> not (isInRange (ch :?> int)) ))

显然我在这里使用了LINQ的`Any'扩展方法。有没有更好的方法来编写上面的代码?


1
它需要包含完整的字母表还是可以有部分字母表? - Sam I am says Reinstate Monica
你的函数返回有效的字符而不是布尔值,这是你想要的吗? - dee-see
@Vache 修复了代码 - fahadash
@SamIam 它可以有重复的字母,但除了字母以外不能有其他任何字符。例如:"this is a correct string","this is ALSO a correct string","but this is not,","so is'nt this one"。 - fahadash
1个回答

7

如果你只是想验证它是否正确,可以这样做:

let isCorrectString(str:string) = 
    let isInRange x = (x > 64 && x < 91 ) || (x > 96 && x < 123) || x = 32
    let bad = 
        str
        |> Seq.map (fun c -> isInRange(int c))
        |> Seq.exists (fun b -> b = false)
    not bad

请注意,这可能是一种更简单的替代方法:
let isCorrectString(str:string) = 
    str
    |> Seq.forall (fun c -> System.Char.IsLetter(c) || c = ' ')

或者,如果您更喜欢:
let isCorrectString(str:string) = 
    str
    |> Seq.tryFind (fun c -> not(System.Char.IsLetter(c) || c = ' '))
    |> Option.isNone

很酷,我宁愿称其为“糟糕”而不是“好”,这样才能表达出正确的意思。 - fahadash
Seq.exists 双重否定后等同于 Seq.forall,是吗?因此 let isCorrectString : string -> bool = Seq.forall (fun c -> System.Char.IsLetter c || System.Char.IsWhiteSpace c) 或者其他什么东西。 - kaefer
5
还有一个函数String.forall,你可以部分应用它来得到 let isCorrectString = String.forall (fun c -> System.Char.IsLetter(c) || c = ' ')。该函数的作用是对字符串中的每个元素执行给定的谓词函数并返回一个布尔值,表示所有元素是否都满足谓词函数的条件。在这里,谓词函数是一个lambda表达式,判断字符是否为字母或空格。 - Daniel
String.forall 在逐个字符处理字符串时比 Seq.forall 快得多,特别是当字符串相对较小的时候。 - latkin
3
值得注意的是,Char.IsLetter 并不等同于检查 a-z + A-ZIsLetter 匹配了许多非英语字符(例如: 'Dž''ʰ''ˁ')。因此,它比手动检查 (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') 要慢一些。 - latkin
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接