Посчитать количество предложений в тексте

OlgaM

Здравствуйте! Подскажите пожалуйста решение моей проблемы. Я пытаюсь сделать так, что из текста, который считывается с файла, я получаю количество предложений. Это в моем коде работает. Но! я не понимаю как расширить программу, чтобы учесть, что точка не всегда обозначает окончание предложения. Точка также может использоваться в качестве сокращений, например и.о.(исполняющий обязаности).

package ir_ub2;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.nio.file.ReadOnlyFileSystemException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class TextCounts { public static void main(String[] args) throws IOException { // datei lesen FileReader fileName = new FileReader("C:\\Users\\Olga\\Desktop\\ub_2\\inputDE.txt"); // wrap a BufferedReader around FileReader BufferedReader reader = new BufferedReader(fileName); int sentenceCount = 0; String line; String terminalSymbol = ".?!"; while ((line = reader.readLine()) != null) { // Continue reading until end of file is reached for (int i = 0; i < line.length(); i++) { if (terminalSymbol.indexOf(line.charAt(i)) != -1) { // If the delimiters string contains the character sentenceCount++; } } } reader.close(); System.out.println("The number of sentences is " + sentenceCount); }
}
8 ответов

OlgaM

Рискуя навлечь на себя гнев всей ленты все таки напишу:

А вы, друзья, как ни садитесь, Все в музыканты не годитесь

Ну если серьезно, то не надо кустарщину, а надо решить задачу по правильному.

Я вижу 2 возможных способа:

  1. Либо засунуть ваш текст в NLP сеть и обучить ее. Для начала можно взять OpenNLP и попробовать обучить ее.
  2. Взять Apache Lucene и попробовать SentenceTokenizer - который разобьет текст на предложения. Lucene, насколько я понимаю, поддерживает русский язык, есть кстати и внешние расширители Lucene для русской морфологии

Как то так.


OlgaM

с такими, различного рода, сокращениями (и.о., т.н., И.С. Тургенев ...). Стоит учитывать количество символов, между точками, либо количество символов до точки. Таких коротких предложений не бывает, следовательно их можно не учитывать. Также можно заложиться на предложения вроде: "Да.", "Нет." Не думаю что таких коротких очень много наберется.

В любом случае, задача бесполезная, имхо.


OlgaM

Навскидку несколько моментов, которые казалось бы простую задачу превращают в нерешаемую:

  1. Парцелляция - не понятно, это одно предложение или все-таки несколько:

    Он тоже пошёл. В магазин. Купить сигарет. (Шукшин)

  2. Предложения с прямой речью:

    Игнат прошептал: "Да ну эту задачу к черту," - и нервно засмеялся.

  3. Ошибки сканирования, опечатки, отсутствие знаков препинания как в типичном интернет-общении. При включенном капсе границы предложения не маркированны никак.

    ВЕДЬ ВСЕ БЫЛО ТАК ПРОСТО ЕЩЕ ПЯТЬ МИНУТ НАЗАД НЕНАВИЖУ

  4. Вкрапления кода:

    Для вывода имени пользователя наберите echo $name . ' ' . $surname.


OlgaM

Это открытая научная задача.

Тут, например люди пытаются ее как-то решить.

Есть библиотека для Питона, которая с этой задачей неплохо справляется(как минимум для английского). Если использовать Яву все-таки очень нужно, см. Jython.


OlgaM

Можно использовать regex:

Matcher m = Pattern.compile("\\.\s*[A-ZА-Я]").matcher(yourText); //Вместо yourText должна быть переменная с текстом, в котором нужно посчитать предложения
int count = 1;
while(m.find()) count++; //Будут сосчитаны все предложения начинающиеся с большой буквы


OlgaM

Вот написал, по моему получилось интересно. Данный код понимает такой вид тестовых предложений.

Привет тест. T..... a Тестирование 34. WHAT???

Вывод

Предложений по моему мнению:4

Также есть дебаг фитчи для теста, он после каждого предложения выводит само предложение. Их можно удалить, а можно использовать.

package javaapplication3;
import java.io.ByteArrayOutputStream;
public class JavaApplication3 { public static void main(String[] args) { String str = "Привет тест. T..... a Тестирование 34. WHAT???"; byte[] bytes = str.getBytes(); byte tocka = '.'; //заставляем интерпретатор из символа точки получить 1 байт(можно цифру, но так понятнее вам будет) byte vopr = '?'; byte voscl = '!'; int count = 0; //храним количество int max = bytes.length; if(max>0){ int i = 0; //сдвиг byte a; //активный байт //ДЕБАГ, В СЛУЧАЕ ИСПОЛЬЗОВАНИЯ СКРИПТА БЕЗ ДЕБАГА ЗАКОМЕНТИТЬ ОТ И ДО ByteArrayOutputStream out = new ByteArrayOutputStream(); //буфер для предложений //дебаг режим выводит уже предложения //РАЗБИРАЕМ while(i


OlgaM

Cвой вопрос мне удалось решить. Для тех, кому интерессно вот мой ответ. Стоит отметить, что задание было для текстов немецкого языка и случаи с сокращением инициалов имени (напр.А.С. Пушкин) учитывать мне не нужно было.

package ir_ub2;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class TextCounts { public static void main(String[] args) throws IOException { FileReader file = new FileReader("inputDE.txt"); // datei lesen BufferedReader reader = new BufferedReader(file); int sentenceCount = 0; String line; String delimiter = ".?!"; String[] singlePointExceptions = { "19. Jahrhundert", "allg.", "bzw.", "bspw.", "etc.", "evtl.", "geb.", "ggf.", "n.Chr", "od.", "s.", "u.", "usw.", "vgl." }; String[] doublePointExceptions = { "b.w.", "d.h.", "d.i", "n.Chr.", "s.a.", "s.o.", "s.u.", "u.a.", "u.Ä.", "u.U.", "u.z.", "v.a.", "v.Chr.", "z.B.", "z.T.", "z.Zt." }; while ((line = reader.readLine()) != null) { // Continue reading until end of file is reached int countQuestionsAndExclamations = countMatchesOfSpecialCharacters(line, "?", "!"); int countSingles = countMatchesOfSpecialCharacters(line, singlePointExceptions); int countDoubles = countMatchesOfSpecialCharacters(line, doublePointExceptions); int countPoints = countMatchesOfSpecialCharacters(line, "."); sentenceCount += (countQuestionsAndExclamations + (countPoints - (countSingles + countDoubles))); } reader.close(); file.close(); System.out.println("# of founded Sentences: " + sentenceCount); } private static int countMatchesOfSpecialCharacters(final String str, final String...specialCharacters) { if (null == str || str.isEmpty()) { return 0; } if (null == specialCharacters || specialCharacters.length == 0) { return 0; } int count = 0; int index = 0; for (int i = 0; i < specialCharacters.length; i++) { String special = specialCharacters[i]; index = 0; while ((index = str.indexOf(special, index)) != -1) { count++; index += special.length(); if (index >= str.length()) { break; } } } return count; }
}


OlgaM

Можешь воспользоваться функцией String.split("."); Функция вернёт массив предложений, а с predlidzenja.length() можно получить длину массива.

licensed under cc by-sa 3.0 with attribution.