【问题标题】:Removing only numbers at beginning of sentences in string - Swift仅删除字符串中句子开头的数字 - Swift
【发布时间】:2021-01-04 19:12:18
【问题描述】:

我需要从字符串中删除数字,但前提是这些数字位于句子的开头。我不想删除句子中的数字。例如:

1房间里有 101 只斑点狗。 2 他们有 2 个父母。 [新行]3 父母被命名为 Pongo 和 Perdita。

在上面的文本中,我想删除每个句子开头的数字,数字后面是否有空格,包括数字是否是换行的第一个字符。所以,字符串中的文本需要变成:

房间里有 101 只斑点狗。他们有2个父母。 [新行]父母被命名为Pongo和Perdita。

感谢您的帮助!

【问题讨论】:

    标签: ios swift string


    【解决方案1】:

    您可以枚举句子,使用正则表达式修剪前导数字,并构建最终字符串。

    例如

    let string = """
        1There were 101 dalmatians in the room. 2 They had 2 parents.
        3 The parents were named Pongo and Perdita.
        """
    
    var result: String = ""
    string.enumerateSubstrings(in: string.startIndex..., options: .bySentences) { substring, _, _, _ in
        guard
            let trimmed = substring?.replacingOccurrences(of: #"^\d+\s*"#, with: "", options: .regularExpression)
        else { return }
        result.append(trimmed)
    }
    print(result)
    

    房间里有 101 只斑点狗。他们有2个父母。
    父母被命名为 Pongo 和 Perdita。

    正则表达式模式有很多排列。例如。如果你使用#"^\d+\.?\)?\s*"#,它也会处理像“1.这是一个测试!”或“1)这是一个测试。”这仅取决于您要处理的变化。但是,如果您只是在寻找数字,无论有无空格,那么#"^\d+\s*"# 应该没问题。

    【讨论】:

    • 你为什么在你的子字符串上使用保护? AFAIK 只能在使用 substringNotRequired 选项 枚举的子字符串时为零。如果在 opts 中包含 substringNotRequired,则每次执行闭包时此参数都为零。 如果我们在选项中不包含 substringNotRequired,它会失败吗?
    • 我通常会安全地打开可选项,而不是假设不可能有一些我可能没有预料到的奇怪的边缘情况。因此,guard 可能不需要,但看起来很谨慎。
    • 感谢您的回答!我对此很陌生,所以我需要一些时间才能正确理解正在发生的事情,但还有很多事情要做。例如,我不知道 Regex。你的回答完全符合我的要求。遗憾的是,我错过了一个需要考虑的组合 - 两边都有字符的数字,例如“.4T”。希望我能找出正则表达式来解决这个问题。再次感谢!
    【解决方案2】:

    这是一个不太花哨的解决方案,它使用基本的 for 循环遍历字符串的每个字符,并使用布尔值来跟踪我们是否在句子开头检查数字。

    var checkForDigit = true // State of loop
    var digitFound = false // Need this to ignore space after digit 
    var output = ""
    for character in text {
        if character.isPunctuation {
            output.append(character)
            checkForDigit = true
            continue
        }
    
        if checkForDigit {
            if !character.isNumber {
                if digitFound && character.isWhitespace {
                    continue
                }
                output.append(character)
                if !character.isWhitespace {
                    checkForDigit = false
                }
            } else {
                digitFound = true
            }
            continue
        }
        digitFound = false
        output.append(character)
    }
    

    我只在问题中的示例上对其进行了测试,因此可能需要一些调整

    【讨论】:

    • 哇,我对你能做到这一点印象深刻!谢谢你的回答。
    【解决方案3】:

    只是为了好玩。您可以枚举句子,获取所有句子范围并替换原始字符串的范围。要从每个句子的开头删除数字,您可以使用收集方法 drop(while:) 并从子字符串(句子)中删除所有非字母字符:

    extension Bool {
        var negated: Bool { !self }
    }
    
    var string = """
    1There were 101 dalmatians in the room. 2 They had 2 parents.
    3 The parents were named Pongo and Perdita.
    """
    var ranges: [Range<String.Index>] = []
    
    string.enumerateSubstrings(in: string.startIndex..., options: .bySentences) { _, range, _, _ in
        ranges.append(range)
    }
    
    for range in ranges.reversed() {
        string.replaceSubrange(range, with: string[range].drop(while: \.isLetter.negated))
    }
    
    string  // "There were 101 dalmatians in the room. They had 2 parents.\nThe parents were named Pongo and Perdita."
    

    【讨论】:

    • 感谢您的回答。正如我上面所说,我是新手,所以我可以从你的建议中学到很多东西。谢谢!
    猜你喜欢
    • 2017-01-23
    • 2015-01-28
    • 1970-01-01
    • 2015-02-03
    • 2016-03-16
    • 1970-01-01
    • 2022-11-28
    • 2015-12-02
    • 2019-11-15
    相关资源
    最近更新 更多