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

Dou*_*oug 5 java regex

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

我要确保我只算合法the的-在theother起不到作用.这意味着我知道我需要以某种方式使用正则表达式.到目前为止我尝试的是:

numSpace += line.split("[^a-z]the[^a-z]").length;  
Run Code Online (Sandbox Code Playgroud)

我意识到正则表达式目前可能不正确,但我试过没有那个,只是试图找到这个词的出现,the我也得到了错误的数字.我认为这会将字符串拆分成一个数组,并且该数组被拆分的次数是字符串中单词的次数.任何想法,我将不胜感激.

更新:鉴于一些想法,我想出了这个:

numThe += line.split("[^a-zA-Z][Tt]he[^a-zA-Z]", -1).length - 1;
Run Code Online (Sandbox Code Playgroud)

虽然仍然有一些奇怪的数字.我能够获得准确的一般计数(没有正则表达式),现在我的问题是正则表达式.

pol*_*nts 9

使用split计数不是最有效的,但如果你坚持这样做,正确的方法是:

haystack.split(needle, -1).length -1                            
Run Code Online (Sandbox Code Playgroud)

如果您没有设置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;
Run Code Online (Sandbox Code Playgroud)

虽然仍然有一些奇怪的数字.我能够获得准确的一般计数(没有正则表达式),现在我的问题是正则表达式.

现在的问题是你没有把[Tt]he它看作是第一个或最后一个词,因为正则表达式说它必须在某个字符之前/之后,匹配的东西[^a-zA-Z](也就是说,你的匹配必须是5的长度! ).你不允许没有角色的情况!

您可以尝试这样的事情:

"(^|[^a-zA-Z])[Tt]he([^a-zA-Z]|$)"
Run Code Online (Sandbox Code Playgroud)

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

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

"(?<![a-zA-Z])[Tt]he(?![^a-zA-Z])"
Run Code Online (Sandbox Code Playgroud)

这样做的好处是只需 匹配[Tt]he,就像你之前的解决方案一样,没有任何额外的字符.这与你真正想要处理返回的标记的情况有关split,因为在这种情况下,分隔符不是从标记"窃取"任何东西.


非-split

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

一个更有效的方法是使用你之前做了同样的正则表达式和做平常Pattern.compilewhile (matcher.find()) count++;


Bah*_*any 5

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

     Pattern pattern = Pattern.compile("Thewordyouwant");
        Matcher matcher = pattern.matcher(string);
        int count = 0;
        while(matcher.find())
            count++;
Run Code Online (Sandbox Code Playgroud)