[英]Java Counting # of occurrences of a word in a string
我有一個大文本文件,我正在閱讀,我需要找出一些單詞出現多少次。 例如,單詞the
。 我逐行做這一行,每一行都是一個字符串。
我要確保我只算合法the
的-在the
在other
起不到作用。 這意味着我知道我需要以某種方式使用正則表達式。 到目前為止我嘗試的是:
numSpace += line.split("[^a-z]the[^a-z]").length;
我意識到正則表達式目前可能不正確,但我嘗試了沒有它,只是試圖找到單詞the
,我也得到錯誤的數字。 我認為這會將字符串拆分成一個數組,並且該數組被拆分的次數是字符串中單詞的次數。 任何想法,我將不勝感激。
更新:鑒於一些想法,我想出了這個:
numThe += line.split("[^a-zA-Z][Tt]he[^a-zA-Z]", -1).length - 1;
雖然仍然有一些奇怪的數字。 我能夠獲得准確的一般計數(沒有正則表達式),現在我的問題是正則表達式。
使用split
to count不是最有效的,但是如果你堅持這樣做,那么正確的方法是:
haystack.split(needle, -1).length -1
如果未將limit
設置為-1
,則split
默認為0
,這將刪除尾隨的空字符串,這會影響您的計數。
來自API :
limit參數控制模式的應用次數,因此會影響結果數組的長度。 [...]如果
n
為零,那么尾隨空字符串將被丟棄。
您還需要從數組的length
中減去1,因為N
次出現的分隔符會將字符串拆分為N+1
部分。
至於正則表達式本身(即needle
),你可以使用\\b
的周圍的字邊界錨word
。 如果允許word
包含元字符(例如,計數出現"$US"
),您可能需要Pattern.quote
它。
我想出來了:
numThe += line.split("[^a-zA-Z][Tt]he[^a-zA-Z]", -1).length - 1;
雖然仍然有一些奇怪的數字。 我能夠獲得准確的一般計數(沒有正則表達式),現在我的問題是正則表達式。
現在的問題是你沒有計算出那個作為第一個或最后一個詞出現的[Tt]he
,因為正則表達式說它必須在某個字符之前/之后,匹配[^a-zA-Z]
(也就是說,你的比賽長度必須是5!)。 你不允許沒有角色的情況!
您可以嘗試這樣的事情:
"(^|[^a-zA-Z])[Tt]he([^a-zA-Z]|$)"
這不是最簡潔的解決方案,但它確實有效。
像這樣的東西(使用負面的外觀 )也有效:
"(?<![a-zA-Z])[Tt]he(?![^a-zA-Z])"
這樣做的好處是只需匹配[Tt]he
,就像你之前的解決方案一樣,沒有任何額外的字符。 這與您實際想要處理split
返回的標記的情況相關,因為在這種情況下,分隔符不會從標記“竊取”任何內容。
split
雖然使用split
to count是相當方便的,但它並不是最有效的(例如,它會做各種工作來返回你丟棄的那些字符串)。 事實上,正如你所說的那樣逐行計數意味着模式也必須重新編譯並丟棄每一行。
一種更有效的方法是使用你之前使用的相同正則表達式並執行通常的Pattern.compile
和while (matcher.find()) count++;
要獲取特定單詞的出現次數,請使用以下代碼
Pattern pattern = Pattern.compile("Thewordyouwant");
Matcher matcher = pattern.matcher(string);
int count = 0;
while(matcher.find())
count++;
為什么不通過Java StringTokenizer運行你的行,然后你可以通過空格而不是逗號和其他標點來分解單詞。 只需瀏覽您的令牌並計算每個“the”或您想要的任何單詞的出現次數。
將這一點擴展並制作一張將每個單詞作為鍵並保持每個單詞使用計數的地圖將非常容易。 此外,您可能需要考慮通過函數運行每個單詞來阻止單詞,這樣您可以計算一個更有用的東西,然后只計算單詞。
拆分字符串聽起來像是為了找出文件中出現次數的大量開銷。 您可以使用String.indexOf(String, int)
遞歸遍歷整行/文件,如下所示:
int occurrences = 0;
int index = 0;
while (index < s.length() && (index = s.indexOf("the", index)) >= 0) {
occurrences++;
index + 3; //length of 'the'
}
我認為這是一個單元測試真正有用的領域。 前段時間我有類似的事情,我希望以多種復雜的方式打破一個字符串並創建一些測試,每個測試都針對不同的源字符串進行測試,幫助我隔離正則表達式並快速查看我弄錯了。
當然,如果你給我們一個測試字符串的例子,結果它會幫助我們給你更好的答案。
您可以嘗試在正則表達式中使用border \\ b一詞:
\bthe\b
此外, split
返回的數組大小將比string
單詞的實際出現次數多1。
使用boyer-moore搜索“the”[在擊中后的字符串的剩余部分]並計算出現次數?
public class OccurenceOfWords {
public static void main(String args[]){
String file = "c:\\customer1.txt";
TreeMap <String ,Integer> index = new TreeMap();
String []list = null;
try( FileReader fr = new FileReader(file);//using arm jdk 7.0 feature
BufferedReader br = new BufferedReader(fr))
{
String line = br.readLine();
while(line!= null){
list = line.split("[ \n\t\r:;',.(){}]");
for(int i = 0 ; i < list.length;i++)
{
String word = list[i].toLowerCase();
if(word.length() != 0)
{
if(index.get(word)== null)
{ index.put(word,1);
}
else
{
int occur = index.get(word).intValue();
occur++;
index.put(word, occur);
}
line = br.readLine();
}
}
}}
catch(Exception ex){
System.out.println(ex.getMessage());
}
for(String item : index.keySet()){
int repeats = index.get(item).intValue();
System.out.printf("\n%10s\t%d",item,repeats);
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.