簡體   English   中英

如何在 Swift 或 Objective-C 中搜索多個多詞短語的字符串

[英]How to search a string for multiple multi-word phrases in Swift or Objective-C

我想解析大量字符串以查找固定短語或名稱,然后將名稱(如果找到)存儲在順序計數的數組中。

例如,以字符串開頭,例如:

str = "The movie stars Robert Duvall and James Earl Jones and pits them against a villain played expertly by Brando in an action packed adventure."

我想搜索一系列演員:

names = [Robert Duvall, Henry Fonda, Brando, Marlon Brando, Jane Fonda, James Earl Jones, Peter Fonda, Montgomery Clift]等等,其中演員可以有一個、兩個或三個名字。

最初,我可以簡單地使用strpos檢查三元組的匹配,或者將字符串轉換為三元組,然后像 James Earl Jones 那樣在三元組上進行匹配。 然后我可以刪除他的名字並在其余部分中搜索其他雙打或單個單詞。 但是,這種方法開始很快變得非常復雜,我想知道是否沒有更優雅的方法。

//這條路看起來確實很亂……

NSArray *triples = [self getTriples:str];//get all combinations of three sequential words
NSArray *pieces = [NSMutableArray new];
NSMutableArray * matches = [NSMutableArray new];
for (long i = 0;i<[triples count];i++) {
   NSString *phrase = triples[i];
   for (long j = 0;j<[names count];j++) {
      NSString *name = names[j];
      if ([phrase caseInsensitiveCompare:name]==NSOrderedSame) {
         [matches addObject:phrase];
         //Rumps has two elements, before and after
         rumps = [str componentsSeparatedByString:phrase];
         NSString *start = rumps[0];
         NSString *end = rumps[1];
         //Search before for a name
         //search after for a name
      }
   }
}//end triples

感謝您的任何建議。

這是基於您的names字符串的想法。

  1. 用逗號拆分names並存儲在數組中,比如a1
  2. 遍歷a1並查看您的全名是否匹配
  3. 如果不是,請再次循環a1並將空格拆分為a2

在這里,我對您的邏輯不是很清楚,但也許是這樣? 現在在這個內部循環中,你循環a2

  1. 如果a2具有三個元素/名稱,那么您假設不匹配? 或者您可以檢查所有可能的組合,對於僅 3 個來說還不錯(已經檢查了 123 個,然后是 132、213、231、312、321,您就完成了 3 個名稱)。
  2. 如果它有兩個元素,則僅反向檢查(21,您已經檢查了 12)。
  3. 如果仍然不匹配,您可以檢查a2的各個元素是否是您想要的,因此請檢查 1、2(可能還有 3)。

您使用相應的a1元素的任何匹配項 - 這就是您想要的全名,對嗎?

您可以使用索引集並將索引設置為a1 - 您發現的防止重復的演員。

這是一個可能的算法草圖,不會有真正的代碼——事實上,在我寫這篇文章時,它還沒有用 Objective-C 或 Swift 編寫,它是一種可以用兩種(和其他)語言實現的算法

在對其進行編碼時,您可能會發現算法遺漏了一些東西(即可能存在錯誤,這是直接寫到答案中的,它是一個草圖,)。 在這種情況下 go 返回並改進算法並重復。

我們的樣品名單:

詹姆斯·厄爾·瓊斯,詹姆斯,馬龍·白蘭度,厄爾·瓊斯,白蘭度,詹姆斯·厄爾

和示例文本:

詹姆斯、詹姆斯厄爾和詹姆斯厄爾瓊斯都定期見面喝咖啡

該算法基於以下觀察結果:

[注意:在描述中,我們假設文本是從左到右的,並且匹配的搜索從左到右移動。 該算法適用於從右到左的簡單調整,對於混合方向的文本,它會變得更加混亂!]

  1. 匹配不能重疊。 例如,“James Earl”不是“James”“James Earl”。 我們說匹配消耗了測試。

  2. 只有作為另一個前綴的名稱需要注意,那些是 *postfixes 的不需要。例如,如果要查找“James”和“James Earl”,您必須首先查找后者以避免在“James”上找到匹配項,然后缺少“James Earl”作為“James”的匹配已經消耗了這些字符。但是“Earl Jones”和“James Earl Jones”可以同時搜索,后者將首先匹配。

  3. 在不包含任何前綴的名稱集合中,它們都可以使用正則表達式同時匹配。 例如 "James Earl Jones" 和 "Earl Jones" 可以由 RE "James Earl Jones|Earl Jones" 匹配

  4. 當您有前綴時,您首先搜索較長的名稱,較短名稱的匹配只能出現在較長名稱的匹配左側。

該算法使用正則表達式匹配,由NSRegularExpression & Swift 中的 NSRegularExpression 提供; 和范圍,由NSRange提供,允許搜索字符串的一部分。

大綱:

  1. 給你的名字排序。 例如:

白蘭度、厄爾·瓊斯、詹姆斯、詹姆斯·厄爾、詹姆斯·厄爾·瓊斯、馬龍·白蘭度

  1. 通過刪除作為緊隨其后名稱前綴的任何名稱並放入第二個列表,將您的名稱分成兩個列表。 例如

白蘭度,厄爾瓊斯,詹姆斯厄爾瓊斯,馬龍白蘭度詹姆斯,詹姆斯厄爾

  1. 如果第二個列表不為空,則重復步驟 (2) 生成第三個列表,繼續重復直到沒有刪除任何前綴。 例如,我們的示例名稱產生 3 個列表:

白蘭度,厄爾瓊斯,詹姆斯厄爾瓊斯,馬龍白蘭度詹姆斯 厄爾詹姆斯

  1. 使用交替將每個列表轉換為正則表達式,以生成用於搜索的正則表達式列表。 例如:

“白蘭度|厄爾瓊斯|詹姆斯厄爾瓊斯|馬龍白蘭度”,“詹姆斯厄爾”,“詹姆斯”

(此時我們意識到樣本名稱可能會更好,因為只有第一個 RE 需要交替。哦,好吧......)

現在我們准備好使用我們准備好的正則表達式來查找匹配項。

  1. 搜索范圍設置為整個文本,匹配范圍為空/無值。

  2. 當前 RE設置為第一個

  3. 使用當前 RE 搜索搜索范圍內的第一個匹配項以生成匹配范圍 如果沒有新的匹配轉到 (9)。 例如,使用我們的示例,其中匹配范圍由 [] 指示:

詹姆斯、詹姆斯·厄爾和 [詹姆斯·厄爾·瓊斯] 都定期見面喝咖啡

  1. 將新的搜索范圍設置為從當前搜索范圍的開始到匹配范圍的結束,前進當前RE,轉到(6)。 例如,名字的匹配順序是:

James, James Earl 和 [James Earl Jones] 都定期見面喝咖啡 James, [James Earl] 和 James Earl Jones [James], James Earl

  1. 我們現在有了我們的第一個匹配范圍,記錄它,將新的搜索范圍設置為從匹配范圍的末尾到文本的末尾,如果這個新的搜索范圍是非空的,則轉到 6。

  2. 完成,我們有匹配列表。

如果您不想要實際匹配的列表,而只想要一組唯一匹配,則在 go 中累積一組匹配(例如NSMutableSet / Set )。

玩得開心編碼(和精煉,編碼......)算法。 如果您遇到問題,請參考此問答,按原樣描述您的算法,展示您的實現,詳細說明您的問題等,毫無疑問有人會幫助您。 HTH。

暫無
暫無

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

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