Получить количество слов из строки в Unicode (на любом языке)
Я хочу получить количество слов из строки. Это так просто. Загвоздка в том, что строка может быть на непредсказуемом языке.
Итак, мне нужна функция подписи int getWordCount(String)
со следующим примером вывода -
getWordCount("供应商代发发货") => 7
getWordCount("This is a sentence") => 4
Любая помощь о том, как действовать, будет принята с благодарностью:)
5 ответов
Понятие "слово" может быть тривиальным или сложным. Вот Apache Stanbol Toolkit:
Токенизация слова: для обработки текста Stanbol Enhancer обнаруживает отдельные слова. Хотя это тривиально для большинства языков, это довольно сложная задача для некоторых восточных языков, например, китайского, японского, корейского. Если не настроено иначе, Stanbol будет использовать пробелы для токенизации слов.
Поэтому, если понятие слова является лингвистическим, а не синтаксическим, вы должны использовать инструментарий НЛП
Я предпочитаю Java-решение - Apache Open NLP.
ПРИМЕЧАНИЕ. Я использовал http://www.mdbg.net/chindict/chindict.php?page=worddict для обозначения вашего примера. Это означает, что есть 4 слова, а не семь. Я вырезал и вставил (довольно фрагментарно):
Исходный текст Упрощенный английский Pīnyīn Добавить новое слово в словарь Традиционный HSK 供应商 供应商 gōng yìng shāng
поставщик
商 商 代 代 dài
заменить / действовать от имени других / заменить / поколение / династия / возраст / период / (историческая) эра / (геологический) эон
发 发 фа
отправить / показать (по ощущениям) / выдать / разработать / классификатор для выстрелов (раундов)
SK HSK 4
发 фа
волосы / Тайвань пр. [FA3]
Hu 发货 发货 фа хуо
отправить / отправить товар
發貨
Эти первые три символа образуют одно слово.
Стандартный API предоставляет BreakIterator для такого рода анализа границ, но поддержка локали Oracle Java 7 не нарушает пример строки.
Когда я использовал ICI4J v51.1 BreakIterator, он разбил образец на [供应, 商代, 发, 发, 货]
,
// import com.ibm.icu.text.BreakIterator;
String sentence = "\u4f9b\u5e94\u5546\u4ee3\u53d1\u53d1\u8d27";
BreakIterator iterator = BreakIterator.getWordInstance(Locale.CHINESE);
iterator.setText(sentence);
List<String> words = new ArrayList<>();
int start = iterator.first();
int end = iterator.next();
while (end != BreakIterator.DONE) {
words.add(sentence.substring(start, end));
start = end;
end = iterator.next();
}
System.out.println(words);
Примечание: я использовал Google Translate, чтобы догадаться, что "供应商代发发货" был китайский. Очевидно, я не говорю на языке, поэтому не могу комментировать правильность вывода.
Если мы предположим, что у каждого языка есть один (или более) разделитель слов, и вы можете построить регулярное выражение для этого разделителя, тогда проблему можно решить следующим образом:
public String separatorForLanguage(char unicodeChar){
// Find out in which language unicodeChar falls
return ""; // return regex of separator of that language
}
public int wordCount(String sentance){
char unicodeChar = sentance.charAt(0);
String separator = separatorForLanguage(unicodeChar);
int count = sentance.split(separator).length;
if (separator.isEmpty()) {
count--;
}
return count;
}
Вот фрагмент в Java
public static int getWordCount(String string)
{
Pattern pattern = Pattern.compile("[\\w']+|[\\u3400-\\u4DB5\\u4E00-\\u9FCC]");
Matcher matcher = pattern.matcher(string);
int count = 0;
while(matcher.find())
count++;
return count;
}
пример
//count is 5
int wordCount = getWordCount("this is popcorny's 電腦");
английская версия
Для английской версии вы можете сделать с довольно простым Regex. Возможно, я пропустил некоторые пользовательские разделители, но:
public static int getWordCount(String str) {
return str.split("[\\s,;-]+").length;
}
Regex объяснение:
Разделите, если найдете кого-либо в группе []
:
[
\\s Any whitespace character or
, A comma
; or a semi-colon
]
+ Followed by any patterns in the group any number of times
китайская версия
Для китайской версии вам необходимо определить разделители. Если вы получите код символа Unicode для китайских разделителей и добавите их к приведенному выше регулярному выражению, вы получите желаемый результат.
тесты
System.out.println(getWordCount("This is a sentence"));// 4
System.out.println(getWordCount("This is a sentence")); // 4
System.out.println(getWordCount("This is a ,,sentence")); // 4