Swift5中如何判断String是否只有字母和空格?

How to check whether String only consists of letters and spaces in Swift 5?

我目前正在尝试验证名称输入字段。为此,我想检查输入。

输入的是一个字符串,只能由字母和空格组成。有什么简单的实现方法吗

例如,我有 "Jon Doe" 的输入,我如何验证这是一个可接受的名称,而 Peter2Ben&Jerry 不是?

提前感谢您的帮助。 <3

let lettersAndSpacesCharacterSet = CharacterSet.letters.union(.whitespaces).inverted

let testValid1 = "Jon Doe".rangeOfCharacter(from: lettersAndSpacesCharacterSet) == nil // true
let testInvalid1 = "Ben&Jerry".rangeOfCharacter(from: lettersAndSpacesCharacterSet) == nil // false
let testInvalid2 = "Peter2".rangeOfCharacter(from: lettersAndSpacesCharacterSet) == nil // false

你也可以这样做

func onlyLettersChecker(string: String) -> Bool {

    let justLettersRegex = "[^A-Za-zÀ-ÖØ-öø-ÿ]"

    let trimmedString = string.replacingOccurrences(of: " ", with: "")
    return trimmedString.isEmpty == false && trimmedString.range(of: justLettersRegex, options: .regularExpression) == nil
}

您删除字符串中的空格,然后检查那里是否只有字母。

正则表达式接受名称中的重音符号,如果您的名称中需要一些撇号等,您可能需要修改正则表达式。

根据具体要求,RegEx 可能是更好的路线。

  • 前导/尾随/额外空格有效吗?
  • 扩展的拉丁字符有效吗?
  • 带标点符号的名称是否有效(连字符或撇号)?

例如,对于 "name" 个条目的列表:

    "Jon Doe",
    "Ben&Jerry",
    "JonDoe",
    "Jon Edward Doe",
    " Jon Doe",
    "Jon   Doe",
    "Jon Doe ",
    "Jon Doe2",
    "José Doe",
    "Jon O'Doe",
    "Jon Doe-Smith",
    "Joß Müller",
    "Jon 黒澤明"

哪些应该有效?

编辑: 根据 Rob 的回答更新了更好的 (?) RegEx...

使用此代码,它使用 .rangeOfCharacter 和 RegEx 测试评估条目:

class ViewController: UIViewController {

    override func viewDidLoad() {

        let names: [String] = [
            "Jon Doe",
            "Ben&Jerry",
            "JonDoe",
            "Jon Edward Doe",
            " Jon Doe",
            "Jon   Doe",
            "Jon Doe ",
            "Jon Doe2",
            "José Doe",
            "Jon O'Doe",
            "Jon Doe-Smith",
            "Joß Müller",
            "Jon 黒澤明",
        ]

        names.forEach {
            test([=11=])
        }

    }

func test(_ text: String) -> Void {

        let ss = "^[\p{L}\p{P}]+\s[\p{L}\p{P}]+$"

        let b1 = text.range(of: ss, options: .regularExpression) != nil

        let lettersAndSpacesCharacterSet = CharacterSet.letters.union(.whitespaces).inverted

        let b2 = text.rangeOfCharacter(from: lettersAndSpacesCharacterSet) == nil

        print("RegEx:", b1, "\t", "Range:", b2, "\t", "[\(text)]")

    }

}

输出为:

RegEx: true      Range: true     [Jon Doe]
RegEx: false     Range: false    [Ben&Jerry]
RegEx: false     Range: true     [JonDoe]
RegEx: false     Range: true     [Jon Edward Doe]
RegEx: false     Range: true     [ Jon Doe]
RegEx: false     Range: true     [Jon   Doe]
RegEx: false     Range: true     [Jon Doe ]
RegEx: false     Range: false    [Jon Doe2]
RegEx: true      Range: true     [José Doe]
RegEx: true      Range: false    [Jon O'Doe]
RegEx: true      Range: false    [Jon Doe-Smith]
RegEx: true      Range: true     [Joß Müller]
RegEx: true      Range: true     [Jon 黒澤明]

你必须决定你想变得多么宽容。西方常见的例外情况包括:

  • 双管齐下的名字(“Daniel Day-Lewis”);
  • 口音(“何塞·穆里尼奥”);
  • 撇号(“克里斯·奥多德”);
  • 血统缩写(“小马丁·路德·金”)、头衔(“李文亮博士”)和证书(“约翰·纳什,Ph.D”)

此外,如果您最终将应用程序本地化为其他语言,您可能需要

  • 非西方字符集(“黑泽明”)

正则表达式可以优雅地处理这些东西,例如这适用于任何字母和一些 select 标点符号:

let searchString = #"^([\p{L},.'’-]+(\s|$))+"#

if string.range(of: searchString, options: .regularExpression) != nil {
    print(string, "passed")
} else {
    print(string, "failed")
}

如果您不想使用句点或逗号,请随意将它们从上述正则表达式中删除。