您好,登錄后才能下訂單哦!
本篇內容主要講解“利用Java實現簡易的分詞器”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“利用Java實現簡易的分詞器”吧!
生活中常見的搜索功能大概可分為以下幾類:
單關鍵詞。如“Notebook”
雙關鍵詞加空格。如“Super Notebook”
多關鍵詞加多空格。如“Intel Super Notebook”
當然,還有四甚至五關鍵詞,這些搜索場景在生活中可以用罕見來形容,不在我們的討論范圍。我們今天就以上三種生活中最常見的搜索形式進行探討分析。業務需求也很簡單,假設我們要完成一個搜索功能,業務層、持久層、控制層不在我們討論的范圍,僅討論分詞功能如何實現。
假設用戶鍵入的搜索內容為以下內容:
Intel Super Notebook
我們可以利用Java中String強大而豐富的方法來慢慢拼湊一個小算法來達到目的。String中大多數方法的參數和返回值都與下標相關,那么,分析上述語句的下標,我們可發現如下內容:
上述內容紅色是我們分詞的關鍵內容。對于一個語句而言(不是語言學上通俗的語句,因為該句沒有主謂賓),重要的就是各單詞或詞組的首字母下標與該單詞或詞組后面最近一個空格。我們發現,Intel
這個單詞首字母下標為0,距離該單詞后面最近的一個空格下標為5;Super
首字母下標為距離該單詞前面最近的一個空格的下標加1,也就是6;Notebook
首字母下標為距離該單詞前面最近的一個空格的下標加1,也就是12;最后就是該語句的尾下標,也就是19。
當然,實際情況會有用戶多輸入了兩個甚至三個空格在某兩個單詞之間,例如如下形式:
Intel Super Notebook
(注意這里的空格為每個單詞之間為2個)
這個問題很容易解決,我們把兩個或三個空格替換為一個空格即可(為什么不是四個或者更多?因為現實情況是用戶不太可能在各個單詞之間連按多個空格),如下:
sentence = sentence.replace(" ", " "); sentence = sentence.replace(" ", " ");
這樣以來語句中就只存在單個空格了。
經過分析我們得知,若想對一個語句進行分詞,就必須知道各個單詞的起始下標才行。起始下標可以由空格的下標得知,那我們該如何得知空格的下標?
很簡單,我們寫個方法,通過迭代語句的每個單詞,判斷其是否存在空格即可。方法如下:
private int firstPosition(){ int first = 0; for(int i = 0; i < sentence.length(); i++){ if(String.valueOf(sentence.charAt(i)).equals(" ")){ first = i; return first; } } return first; }
這個方法的作用是判斷一個語句中第一個空格的位置。既然有第一個了,肯定要有第二個了。要注意第一個內容是從0開始進行迭代,而第二個空格的判斷方法要從第一個空格的位置加1開始,否則迭代的剛好還是第一個空格的位置。內容如下:
private int secondPosition(){ int second = 0; for(int i = (firstPosition() + 1); i < sentence.length(); i++){ if(String.valueOf(sentence.charAt(i)).equals(" ")){ second = i; return second; } } return second; }
第三個為什么不迭代?因為第三個單詞之后就沒有空格了,就到結尾了。
找出每個空格的下標索引后,我們還需知道語句中含有多少個空格,是沒有,還是1個或2個(連續的重復空格在上文已經被替換為單個空格了)。方法如下:
private int countBlank(String s){ // Store single blank signal. int amount = 0; // If s contains single blank signal, and it will increse amount's value of 1 every loop times. for(int i = 0; i < s.length(); i++){ if(String.valueOf(sentence.charAt(i)).equals(" ")){ amount++; } } return amount; }
拿到了空格的總個數及每個空格的下標,我們就可以寫個方法進行分割了。由于我是采用了泛型集合作為數據源,這里的方法返回類型就為void。
我們先假設輸入的僅有以下內容:
Intel
輸入的僅有一個詞組。我們先判斷其空格的個數,發現為0,那么也不用進行什么操作了,直接添加其作為集合的數據。
public void divide(){ // Record every single blank signal's position. int position1 = firstPosition(); int position2 = secondPosition(); if(sentence.contains(" ")){ } else{ words.add(sentence); } }
現在情況變為輸入的內容如下:
Intel Super
我們知道了這個語句共有一個空格,下標為5,長度為11,那可以這樣判斷:是否包含空格,如果是,那就判斷其空格數是否大于等于0,如果為真,就添加到數據源。接著判斷其空格數是否大于等于1,如果真,進入下一層判斷其空格數是否大于等于1其小于2,如果真,就添加到數據源。內容如下:
public void divide(){ // Record every single blank signal's position. int position1 = firstPosition(); int position2 = secondPosition(); if(sentence.contains(" ")){ int blankAmount = countBlank(sentence); if (blankAmount >= 0) { words.add(sentence.substring(0, position1)); if (blankAmount >= 1) { if(blankAmount >= 1 && blankAmount < 2))); words.add(sentence.substring(position1, sentence.length())); } else { } } } } else{ words.add(sentence); } }
下面就是較為全面的情況了:
Intel Super Notebook
我們判斷完兩個情況就看第三個情況。第三個單詞其獲取是通過第二個空格下標與語句長度得來。但第二個單詞就要改為第一個空格下標加1與第二個空格下標加1了。那么至此分割方法也就完成了:
public String divide(){ // Record every single blank signal's position. int position1 = firstPosition(); int position2 = secondPosition(); if(sentence.contains(" ")){ int blankAmount = countBlank(sentence); if (blankAmount >= 0) { words.add(sentence.substring(0, position1)); if (blankAmount >= 1) { if(blankAmount >= 1 && blankAmount < 2){ words.add(sentence.substring(position1, sentence.length())); } else { words.add(sentence.substring(position1, position2)); if (blankAmount >= 2) { words.add(sentence.substring(position2, sentence.length())); } } } } } else{ words.add(sentence); } }
Intel Super Notebook
SIZE:3
POSITION(0): Intel
POSITION(1): Super
POSITION(2): Notebook
Intel Super Notebook
(注這里有重復且連續的空格)
SIZE:3
POSITION(0): Intel
POSITION(1): Super
POSITION(2): Notebook
英特爾 超級 筆記本
SIZE:3
POSITION(0): 英特爾
POSITION(1): 超級
POSITION(2): 筆記本
華為
SIZE:1
POSITION(0): 華為
class DivideWord{ private String sentence; private List<String> words = new ArrayList<String>(); public DivideWord(String sentence) { // Replace two or three blank signal that connected into single blank signal. sentence = sentence.replace(" ", " "); sentence = sentence.replace(" ", " "); this.sentence = sentence; } private int countBlank(String s){ // Store single blank signal. int amount = 0; // If s contains single blank signal, and it will increse amount's value of 1 every loop times. for(int i = 0; i < s.length(); i++){ if(String.valueOf(sentence.charAt(i)).equals(" ")){ amount++; } } return amount; } private int firstPosition(){ int first = 0; for(int i = 0; i < sentence.length(); i++){ if(String.valueOf(sentence.charAt(i)).equals(" ")){ first = i; return first; } } return first; } private int secondPosition(){ int second = 0; for(int i = (firstPosition() + 1); i < sentence.length(); i++){ if(String.valueOf(sentence.charAt(i)).equals(" ")){ second = i; return second; } } return second; } public String divide(){ // Record every single blank signal's position. int position1 = firstPosition(); int position2 = secondPosition(); if(sentence.contains(" ")){ int blankAmount = countBlank(sentence); if (blankAmount >= 0) { words.add(sentence.substring(0, position1)); if (blankAmount >= 1) { if(blankAmount >= 1 && blankAmount < 2){ words.add(sentence.substring(position1, sentence.length())); } else { words.add(sentence.substring(position1, position2)); if (blankAmount >= 2) { words.add(sentence.substring(position2, sentence.length())); } } } } } else{ words.add(sentence); } } public int getSize(){ return words.size(); } public String getWord(int position){ return words.get(position); } } public class DateGet { public static void main(String[] args){ DivideWord divideWord = new DivideWord("英特爾"); divideWord.divide(); System.out.println("SIZE:" + divideWord.getSize()); System.out.println("POSITION :" + divideWord.getWord(0)); } }
到此,相信大家對“利用Java實現簡易的分詞器”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。