摘要:簡介在本快速教程中,將了解如何檢測字符串中的多個單詞。我們的例子我們假設(shè)我們有字符串我們的任務(wù)是查找是否包含和字樣。使用與使用方法的解決方案類似,我們可以使用方法檢查關(guān)鍵字的索引。結(jié)論在本文中,我們學習了如何在字符串中查找多個關(guān)鍵字。
簡介
在本快速教程中,將了解如何檢測字符串中的多個單詞。
我們的例子我們假設(shè)我們有字符串:
String inputString = "hello there, william";
我們的任務(wù)是查找inputString 是否包含“hello”和“william”字樣。
所以,讓我們把我們的關(guān)鍵字放到一個數(shù)組中:
String[] words = {"hello", "william"};
此外,單詞的順序并不重要,匹配要區(qū)分大小寫。
使用String.contains()首先,我們將展示如何使用String.contains()方法來實現(xiàn)我們的目標。
讓我們遍歷關(guān)鍵字數(shù)組并檢查inputString中每個項目的出現(xiàn) :
public static boolean containsWords(String inputString, String[] items) { boolean found = true; for (String item : items) { if (!inputString.contains(item)) { found = false; break; } } return found; }
這個例子比較簡單易懂,盡管我們需要編寫更多代碼,但這種解決方案對于簡單的用例來說速度很快。
使用 String.indexOf()與使用String.contains()方法的解決方案類似,我們可以使用String.indexOf()方法檢查關(guān)鍵字的索引。為此,我們需要一個接受inputString和關(guān)鍵字列表的方法:
public static boolean containsWordsIndexOf(String inputString, String[] words) { boolean found = true; for (String word : words) { if (inputString.indexOf(word) == -1) { found = false; break; } } return found; }
所述的indexOf() 方法返回的內(nèi)部的字的索引inputString。當我們在文本中沒有單詞時,索引將為-1。
使用正則表達式現(xiàn)在,讓我們使用正則表達式來匹配我們的單詞。為此,我們將使用Pattern類。
首先,讓我們定義字符串表達式。由于我們需要匹配兩個關(guān)鍵字,我們將使用兩個前瞻構(gòu)建我們的正則表達式規(guī)則:
Pattern pattern = Pattern.compile("(?=.*hello)(?=.*william)");
對于一般情況:
StringBuilder regexp = new StringBuilder(); for (String word : words) { regexp.append("(?=.*").append(word).append(")"); }
之后,我們將使用matcher()方法find()出現(xiàn)次數(shù):
public static boolean containsWordsPatternMatch(String inputString, String[] words) { StringBuilder regexp = new StringBuilder(); for (String word : words) { regexp.append("(?=.*").append(word).append(")"); } Pattern pattern = Pattern.compile(regexp.toString()); return pattern.matcher(inputString).find(); }
但是,正則表達式具有性能成本。如果我們要查找多個單詞,則此解決方案的性能可能不是最佳的。
使用Java 8和List最后,我們可以使用Java 8的Stream API。但首先,得把初始數(shù)據(jù)進行一些簡單的轉(zhuǎn)換:
ListinputString = Arrays.asList(inputString.split(" ")); List words = Arrays.asList(words);
現(xiàn)在,是時候使用Stream API了:
public static boolean containsWordsJava8(String inputString, String[] words) { ListinputStringList = Arrays.asList(inputString.split(" ")); List wordsList = Arrays.asList(words); return wordsList.stream().allMatch(inputStringList::contains); }
如果輸入字符串包含我們所有的關(guān)鍵字,則上面的操作將返回true。
或者,我們可以簡單地使用Collections框架的containsAll()方法來實現(xiàn)所需的結(jié)果:
public static boolean containsWordsArray(String inputString, String[] words) { ListinputStringList = Arrays.asList(inputString.split(" ")); List wordsList = Arrays.asList(words); return inputStringList.containsAll(wordsList); }
但是,此方法僅適用于整個單詞。因此,只有當它們與文本中的空格分開時才會找到我們的關(guān)鍵字。
使用Aho-Corasick算法簡而言之,Aho-Corasick算法用于使用多個關(guān)鍵字進行文本搜索。無論我們搜索多少關(guān)鍵字或文本長度是多長,它都具有O(n)時間復(fù)雜度
讓我們在pom.xml中包含??Aho-Corasick算法依賴:
org.ahocorasick ahocorasick 0.4.0
首先,通過maven引入依賴包,內(nèi)部的結(jié)構(gòu),將使用樹形數(shù)據(jù)結(jié)構(gòu):
Trie trie = Trie.builder().onlyWholeWords().addKeywords(words).build();
之后,讓我們使用inputString文本調(diào)用解析器方法,我們希望在其中找到關(guān)鍵字并將結(jié)果保存在emits集合中:
Collectionemits = trie.parseText(inputString);
最后,打印運行的結(jié)果:
emits.forEach(System.out::println);
對于每個關(guān)鍵字,我們會在文本中查看關(guān)鍵字的起始位置,結(jié)束位置和關(guān)鍵字本身:
0:4=hello 13:19=william
最后,讓我們看看完整的實現(xiàn):
public static boolean containsWordsAhoCorasick(String inputString, String[] words) { Trie trie = Trie.builder().onlyWholeWords().addKeywords(words).build(); Collectionemits = trie.parseText(inputString); emits.forEach(System.out::println); boolean found = true; for(String word : words) { boolean contains = Arrays.toString(emits.toArray()).contains(word); if (!contains) { found = false; break; } } return found; }
在這個例子中,我們只尋找整個單詞。因此,如果我們不僅要匹配inputString而且還要匹配 helloBaeldung,我們應(yīng)該簡單地從Trie構(gòu)建器管道中刪除 onlyWholeWords()屬性。
此外,請記住,我們還會從emits集合中刪除重復(fù)元素,因為同一關(guān)鍵字可能存在多個匹配項。
結(jié)論在本文中,我們學習了如何在字符串中查找多個關(guān)鍵字。此外,我們通過使用核心JDK以及Aho-Corasick庫來展示示例。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/74034.html
摘要:木易楊注意原始類型被包裝為對象木易楊原始類型會被包裝,和會被忽略。木易楊原因在于時,其屬性描述符為不可寫,即。木易楊解決方法也很簡單,使用我們在進階期中介紹的就可以了,使用如下。 引言 上篇文章介紹了賦值、淺拷貝和深拷貝,其中介紹了很多賦值和淺拷貝的相關(guān)知識以及兩者區(qū)別,限于篇幅只介紹了一種常用深拷貝方案。 本篇文章會先介紹淺拷貝 Object.assign 的實現(xiàn)原理,然后帶你手動實...
摘要:本期推薦文章類內(nèi)存泄漏及如何避免,由于微信不能訪問外鏈,點擊閱讀原文就可以啦。四種常見的內(nèi)存泄漏劃重點這是個考點意外的全局變量未定義的變量會在全局對象創(chuàng)建一個新變量,如下。因為老版本的是無法檢測節(jié)點與代碼之間的循環(huán)引用,會導(dǎo)致內(nèi)存泄漏。 (關(guān)注福利,關(guān)注本公眾號回復(fù)[資料]領(lǐng)取優(yōu)質(zhì)前端視頻,包括Vue、React、Node源碼和實戰(zhàn)、面試指導(dǎo)) 本周正式開始前端進階的第一期,本周的主題...
摘要:接下來,作者從密碼算法的誤用著手,針對一些常量,改進了靜態(tài)分析工具。具體來說,就是在的基礎(chǔ)上做了動態(tài)分析方法和靜態(tài)分析方法相結(jié)合的策略,在線記錄文件,離線檢測分析,使得整個工具更加完善。 ...
摘要:如果值是基本類型,則用操作符檢查其類型??偨Y(jié)所有編程語言都需要可維護性良好的代碼,這個很重要,因為大部分開發(fā)人員都花費大量時間維護他人的代碼。 o(╯□╰)o 這并不是什么史詩巨作,沒有非常深入去挖掘這類問題,只是從平常的JS代碼習慣,參考書籍總結(jié)而來,希望對你有幫助的! 今天的web應(yīng)用大至成千上萬行的javascript代碼,執(zhí)行各種復(fù)雜的過程,這種演化讓我們開發(fā)者必...
閱讀 2050·2021-11-08 13:22
閱讀 2510·2021-09-04 16:40
閱讀 1156·2021-09-03 10:29
閱讀 1723·2019-08-30 15:44
閱讀 2127·2019-08-30 11:13
閱讀 2795·2019-08-29 17:07
閱讀 1972·2019-08-29 14:22
閱讀 1252·2019-08-26 14:00