簡體   English   中英

iOS Swift:在字符串中查找匹配詞的范圍

[英]iOS Swift: looking for ranges of matching word in a string

我需要制作一個 function 來返回給定字符串中匹配單詞的范圍,例如,給定以下句子:

嘿哥們兒。 你的兄弟也是她的兄弟。

我想在句子中找到與單詞“bro”匹配的Range數組,它應該匹配確切的單詞(不區分大小寫),所以“bro”應該只匹配“bro”而不是“brother”。

我想過:

  1. 拆分句子,例如"hey", "bro", "your", "brother", "is", "also", "her", "brother"
  2. map 每個單詞到一個有范圍的單詞,例如“hey”會變成["hey", 0...2]
  3. 過濾和 map 單詞和范圍數組,匹配“bro”

步驟 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)

歸功於 iOS - 正則表達式匹配單詞邊界,包括下划線

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM