Несколько шаблонов регулярных выражений для поиска.Джава - PullRequest
0 голосов
/ 14 мая 2018

Мне нужно отдельно рассчитать количество слов и предложений в строке, и у меня есть два метода, которые отлично работают:

    Pattern pattern = Pattern.compile("\\w+\\s|\\w+\\,|\\w+\\.|\\w+\\?|\\w+\\!*$");
    Matcher match1 = pattern.matcher(s);
    while(match1.find()) {
        counterWords++;
    }   

и для предложений:

    Pattern pattern = Pattern.compile("[^?!.][?!.]");
    Matcher match2 = pattern.matcher(s);
    while(match2.find()) {
        counterSentences++;
    }   

Следующее заданиеэто вычислить его снова, но в одном цикле, поэтому я попытался:

while(match1.find() || match2.find()){
    if(match1.find()){
        counterWords++;
    }
    if(match2.find()){
        counterSentences++;
    }

Тем не менее, метод не работает должным образом, он правильно считает предложения, но счетчик слов в 2 раза меньше, чем фактическое количество слов,Скорее всего, я не совсем понимаю, как работает matcher.find (), может кто-нибудь объяснить, что я делаю неправильно?Спасибо.

Ответы [ 2 ]

0 голосов
/ 15 мая 2018

Чтобы решить эту проблему с помощью одного цикла, вам нужно, чтобы ваш сопоставитель нашел либо слова, либо маркеры конца предложения, а затем сообщил вам, что он нашел.Это можно сделать с помощью «групп захвата».

    String s = "Hello, user.  How many words and sentences are there?  Count them!";

    int words = 0;
    int sentences = 0;
    Pattern pattern = Pattern.compile("(\\w+)|([.?!])");
    Matcher matcher = pattern.matcher(s);

    while(matcher.find()) {
        if (matcher.group(1) != null)
            words++;
        else if (matcher.group(2) != null)
            sentences++;
    }

    System.out.printf("%d words and %d sentences%n", words, sentences);

11 слов и 3 предложений

Объяснение регулярного выражения:

(\w+)|([.?!]) - послеперевод \\ в \
(___)________ - группа захвата # 1.
_\w+_________ - один или несколько символов слова.
_____|_______ - соответствует первой части выражения илиsecond.
______(_____) - группа захвата # 2.
_______[.?!]_ - символ-терминатор предложения.

Первый вызов matcher.find() будет соответствовать Hello, записывая его как группу захвата.# 1.Следующий вызов пропускается через запятую и пробел и соответствует user, снова записывая его как группу захвата # 1.Третий вызов соответствует периоду (.) во второй части регулярного выражения, записывая его как группу захвата # 2.Это продолжается до совпадения восклицательного знака (!).Следующий вызов matcher.find() возвращает значение false, поскольку совпадений больше не найдено.

Операторы if проверяют, были ли заполнены захваты группы № 1 или группы № 2, что определяет, будет ли слово илиОбнаружен терминатор предложения.

0 голосов
/ 14 мая 2018

Каждый вызов find () будет искать следующее совпадение и в вашем комбинированном цикле while, который вы вызываете find () дважды в каждом цикле для match1 и match2, сначала в условии while, а затем снова в условиях if, но Вы только увеличиваете счетчик для второй находки.

Кроме того, так как вы впервые вызываете find () для слов, в то время как условие find () для предложений никогда не будет вызываться, поскольку всегда есть равные или больше слов, чем предложения, и счетчик предложений будет работать правильно.

...