components由Swift中的多个分隔符分隔

问题描述 投票:3回答:5

所以这里是字符串s

"Hi! How are you? I'm fine. It is 6 p.m. Thank you! That's it."

我希望它们被分隔为一个数组:

["Hi", "How are you", "I'm fine", "It is 6 p.m", "Thank you", "That's it"]

这意味着分隔符应该是". " + "? " + "! "

我试过了:

let charSet = NSCharacterSet(charactersInString: ".?!")
let array = s.componentsSeparatedByCharactersInSet(charSet)

但它也将p.m.分为两个元素。结果:

["Hi", " How are you", " I'm fine", " It is 6 p", "m", " Thank you", " That's it"]

我也试过了

let array = s.componentsSeparatedByString(". ")

它适用于分离". ",但如果我也想分开"? ""! ",它会变得混乱。

所以我能做到这一点吗?谢谢!

ios swift split string-split
5个回答
5
投票

提供了一种允许枚举字符串的方法。您可以通过单词或句子或其他选项来完成此操作。不需要正则表达式。

let s = "Hi! How are you? I'm fine. It is 6 p.m. Thank you! That's it."
var sentences = [String]()
s.enumerateSubstringsInRange(s.startIndex..<s.endIndex, options: .BySentences) { 
    substring, substringRange, enclosingRange, stop in
    sentences.append(substring!)
}
print(sentences)

结果是:

[“嗨!”,“你好吗?”,“我没事。”,“现在是下午6点”,“谢谢!”,“就是这样。”]


3
投票

rmaddy的回答是正确的(+1)。 Swift 3的实现是:

var sentences = [String]()

string.enumerateSubstrings(in: string.startIndex ..< string.endIndex, options: .bySentences) { substring, substringRange, enclosingRange, stop in
    sentences.append(substring!)
}

你也可以使用正则表达式NSRegularExpression,虽然它比rmaddy的.bySentences解决方案更加毛茸茸。在Swift 3中:

var sentences = [String]()

let regex = try! NSRegularExpression(pattern: "(^|\\s+)(\\w.*?[.!?]+)(?=(\\s+|$))")
regex.enumerateMatches(in: string, range: NSMakeRange(0, string.characters.count)) { match, flags, stop in
    sentences.append((string as NSString).substring(with: match!.rangeAt(2)))
}

或者Swift 2:

let regex = try! NSRegularExpression(pattern: "(^|\\s+)(\\w.*?[.!?]+)(?=(\\s+|$))", options: [])
var sentences = [String]()
regex.enumerateMatchesInString(string, options: [], range: NSMakeRange(0, string.characters.count)) { match, flags, stop in
    sentences.append((string as NSString).substringWithRange(match!.rangeAtIndex(2)))
}

[.!?]语法匹配这三个字符中的任何一个。 |的意思是“或”。 ^匹配字符串的开头。 $匹配字符串的结尾。 \\s匹配空白字符。 \\w匹配“单词”字符。 *匹配前面字符的零个或多个。 +匹配前面一个或多个字符。 (?=)是一个前瞻性断言(例如,看看那里有什么东西,但不要通过那场比赛前进)。

我试图简化这一点,但它仍然非常复杂。正则表达式提供了丰富的文本模式匹配,但是,不可否认,当您第一次使用它时它会有点密集。但是这种表现与(a)重复的标点符号(例如"Thank you!!!"),(b)前导空格和(c)尾随空格相匹配。


1
投票

如果分裂基础比句子更深奥,那么这种扩展可以起作用。

extension String {
    public func components(separatedBy separators: [String]) -> [String] {
        var output: [String] = [self]
        for separator in separators {
            output = output.flatMap { $0.components(separatedBy: separator) }
        }
        return output.map { $0.trimmingCharacters(in: .whitespaces)}
    }
}

let artists = "Rihanna, featuring Calvin Harris".components(separated by: [", with", ", featuring"])

0
投票

我试图找到一个正则表达式来解决这个问题:(([^.!?]+\s)*\S+(\.|!|\?))这里来自regexperexample的解释


0
投票

好吧,我也从here找到了一个正则表达式

var pattern = "(?<=[.?!;…])\\s+(?=[\\p{Lu}\\p{N}])"

let s = "Hi! How are you? I'm fine. It is 6 p.m. Thank you! That's it."

let sReplaced = s.stringByReplacingOccurrencesOfString(pattern, withString:"[*-SENTENCE-*]" as String, options:NSStringCompareOptions.RegularExpressionSearch, range:nil)

let array = sReplaced.componentsSeparatedByString("[*-SENTENCE-*]")

也许这不是一个好方法,因为它必须首先替换并分离字符串。 :)

更新:

对于正则表达式部分,如果您还想匹配中文/日文标点符号(不需要每个标点符号后的空格),您可以使用以下标点符号:

((?<=[.?!;…])\\s+|(?<=[。!?;…])\\s*)(?=[\\p{L}\\p{N}])
最新问题
© www.soinside.com 2019 - 2024. All rights reserved.