使用 split
进行计数并不是最有效的方法,但如果您坚持这样做,正确的方式是:
haystack.split(needle, -1).length -1
如果您没有将
limit
设置为
-1
,则
split
默认为
0
,这会移除尾随空字符串,从而使您的计数出错。
从
API中可以看出:
limit参数控制模式应用的次数,从而影响生成的数组长度。如果n
为零,则丢弃尾随的空字符串。
您还需要从数组的
length
中减去1,因为定界符的
N
个出现将字符串分成
N+1
部分。
关于正则表达式本身(即
needle
),您可以在
word
周围使用单词边界锚点
\b
。如果您允许
word
包含元字符(例如计算
"$US"
的出现次数),则可能要使用
Pattern.quote
。
I've come up with this:
numThe += line.split("[^a-zA-Z][Tt]he[^a-zA-Z]", -1).length - 1
Though still getting some strange numbers. I was able to get an accurate general count (without the regular expression), now my issue is with the regexp.
现在问题是你没有计算出现在第一个或最后一个单词的“the”,因为正则表达式指定它必须在某个字符前面/后面,匹配
[^a-zA-Z]
(也就是说,你的匹配必须长度为5!)你没有考虑根本没有字符的情况!
你可以尝试使用以下内容:
"(^|[^a-zA-Z])[Tt]he([^a-zA-Z]|$)"
这不是最简洁的解决方案,但它可以工作。
使用负向环视(negative lookarounds)也可以像下面这样实现:
"(?<![a-zA-Z])[Tt]he(?![^a-zA-Z])"
这样做的好处是只匹配
仅有的[Tt]he
,没有像之前的解决方案一样在它周围添加任何额外的字符。如果你实际上想要处理
split
返回的标记,这点非常重要,因为在这种情况下分隔符并不会从标记中“窃取”任何信息。
非split
虽然使用split
来计数相当方便,但它并不是最有效的方法(例如,它正在执行各种工作以返回那些你丢弃的字符串)。正如你所说,你是逐行计数的,这意味着模式也必须在每行重新编译和丢弃。
更有效的方法是使用与之前相同的正则表达式,并进行通常的Pattern.compile
和while (matcher.find()) count++;
操作。