Java Counting字符串中单词出现次数

我有一个大文本文件,我正在阅读,我需要找出一些单词出现多少次。 例如,单词the 。 我一行一行地每行都是一个字符串。

我需要确保我只计算合法性 – other人不会计算。 这意味着我知道我需要以某种方式使用正则表达式。 到目前为止我尝试的是:

 numSpace += line.split("[^az]the[^az]").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包含元字符(例如,计数出现"$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]|$)" 

这不是最简洁的解决方案,但它有效。

像这样的东西(使用负面的外观 )也有效:

 "(? 

这样做的好处是只需匹配[Tt]he ,就像你之前的解决方案一样,没有任何额外的字符。 这与您实际想要处理split返回的标记的情况相关,因为在这种情况下,分隔符不会从标记“窃取”任何内容。


split

虽然使用split to count是相当方便的,但它并不是最有效的(例如,它会做各种工作来返回你丢弃的字符串)。 事实上,正如你所说的那样逐行计数意味着模式也必须重新编译并丢弃每一行。

一种更有效的方法是使用你之前使用的相同正则表达式并执行通常的Pattern.compilewhile (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' } 

要获取特定单词的出现次数,请使用以下代码

  Pattern pattern = Pattern.compile("Thewordyouwant"); Matcher matcher = pattern.matcher(string); int count = 0; while(matcher.find()) count++; 

我认为这是一个unit testing真正有用的领域。 前段时间我有类似的事情,我希望以多种复杂的方式打破一个字符串并创建一些测试,每个测试都针对不同的源字符串进行测试,帮助我隔离正则表达式并快速查看我弄错了。

当然,如果你给我们一个测试字符串的例子,结果它将帮助我们给你更好的答案。

您可以尝试在正则表达式中使用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  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); } } }