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