Использование split
для подсчета - не самый эффективный способ, но если вы настаиваете на этом, то правильный путь таков:
haystack.split(needle, -1).length -1
Если вы не установите limit
на -1
, split
по умолчанию будет 0
, что удаляет завершающие пустые строки, что портит ваш счет.
С API :
Параметр limit определяет количество применений шаблона и, следовательно, влияет на длину результирующего массива. [...] Если n
равно нулю, то [...] завершающие пустые строки будут отброшены.
Вам также необходимо вычесть 1 из length
массива, поскольку вхождения N
разделителя разбивают строку на N+1
частей.
Что касается самого регулярного выражения (то есть needle
), вы можете использовать \b
якоря границы слова вокруг word
. Если вы разрешите word
содержать метасимволы (например, число вхождений "$US"
), вы можете Pattern.quote
it.
Я придумал это:
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
, потому что в этом случае разделитель не «крадет» что-либо из токенов.
Non- split
Хотя использование split
для подсчета довольно удобно, это не самый эффективный (например, он выполняет все виды работы, чтобы вернуть те строки, которые вы отбрасываете). Тот факт, что, как вы сказали, вы рассчитываете построчно, означает, что шаблон также придется перекомпилировать и отбрасывать каждую строку.
Более эффективный способ - использовать те же регулярные выражения, которые вы использовали ранее, и выполнять обычные Pattern.compile
и while (matcher.find()) count++;
.