[英]iOS Swift: looking for ranges of matching word in a string
我需要制作一個 function 來返回給定字符串中匹配單詞的范圍,例如,給定以下句子:
嘿哥們兒。 你的兄弟也是她的兄弟。
我想在句子中找到與單詞“bro”匹配的Range
數組,它應該匹配確切的單詞(不區分大小寫),所以“bro”應該只匹配“bro”而不是“brother”。
我想過:
"hey", "bro", "your", "brother", "is", "also", "her", "brother"
["hey", 0...2]
步驟 2 需要進行一些處理以確保每個單詞(在句子中)的范圍可以映射到正確的單詞,例如第一個“兄弟”和第二個“兄弟”應該根據它們所在的位置而具有不同的范圍。
有沒有更聰明的方法來做到這一點?
編輯:
抱歉,我忘了說,不使用 Regex 的原因是有時單詞中有一個點,例如:
籃子里有橘子。
從上面的句子中,使用正則表達式查找字符串“or.ge”也將匹配“橙色”。
一種簡單的解決方案是使用帶有\b
的正則表達式來匹配“單詞邊界”,例如
let searchString = "bro"
let sentence = "Hey, Bro! Your brother is also her brother."
let regex = try! NSRegularExpression(pattern: #"\b\#(searchString)\b"#, options: .caseInsensitive)
regex.enumerateMatches(in: sentence, range: NSRange(sentence.startIndex..., in: sentence)) { match, _, _ in
guard let match = match else { return }
print(match.range)
// or, if you want a String.Range
if let range = Range(match.range, in: sentence) {
print(sentence[range])
}
}
還有其他更豐富的 API(例如自然語言框架),雖然不完美,但提供了更豐富的自然語言文本解析。 例如,下面將區分動詞“saw”和名詞“saw”:
import NaturalLanguage
let text = "I saw the hammer. I did not see a saw."
let tagger = NLTagger(tagSchemes: [.lexicalClass])
tagger.string = text
let options: NLTagger.Options = [.omitWhitespace, .joinContractions]
tagger.enumerateTags(in: text.startIndex..<text.endIndex, unit: .word, scheme: .lexicalClass, options: options) { tag, range in
guard let tag = tag else { return true }
print(tag, String(text[range]))
return true
}
生產:
NLTag(_rawValue:代詞)我
NLTag(_rawValue: Verb) 看到
NLTag(_rawValue:Determiner)
NLTag(_rawValue: 名詞) 錘子
NLTag(_rawValue:SentenceTerminator)。
NLTag(_rawValue:代詞)我
NLTag(_rawValue: Verb) 做了
NLTag(_rawValue: 副詞) 不是
NLTag(_rawValue: 動詞) 見
NLTag(_rawValue: 確定器) a
NLTag(_rawValue: 名詞) 鋸
NLTag(_rawValue:SentenceTerminator)。
我在 Playground 中進行了測試,您可以使用此擴展來獲取與此 reg ex 匹配的值。
extension String {
func ranges(of substring: String, options: CompareOptions = [], locale: Locale? = nil) -> [Range<Index>] {
var ranges: [Range<Index>] = []
while ranges.last.map({ $0.upperBound < self.endIndex }) ?? true,
let range = self.range(of: substring, options: options, range: (ranges.last?.upperBound ?? self.startIndex)..<self.endIndex, locale: locale)
{
ranges.append(range)
}
return ranges
}
}
let searchString = "bro"
var str = "Hey, bro! Your brother is also her brother."
var reg = str.ranges(of: "(?<![\\p{L}\\d])\(searchString)(?![\\p{L}\\d])", options: [.regularExpression, .caseInsensitive])
str.removeSubrange(reg.first!)
print(str)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.