【发布时间】:2011-01-07 09:32:38
【问题描述】:
有什么简单的方法可以用纯 Java 创建句子解析器 不添加任何库和罐子。
解析器不应该只关注单词之间的空格, 但要更聪明并解析:. ! ?, 识别句子何时结束等。
解析后,只有真实的单词可以全部存储在db或file中,而不是任何特殊字符。
提前非常感谢大家:)
【问题讨论】:
-
也可以考虑
StreamTokenizer;它是fast,可以灵活地容纳空白。
有什么简单的方法可以用纯 Java 创建句子解析器 不添加任何库和罐子。
解析器不应该只关注单词之间的空格, 但要更聪明并解析:. ! ?, 识别句子何时结束等。
解析后,只有真实的单词可以全部存储在db或file中,而不是任何特殊字符。
提前非常感谢大家:)
【问题讨论】:
StreamTokenizer;它是fast,可以灵活地容纳空白。
您可能希望从查看 BreakIterator 类开始。
来自 JavaDoc。
BreakIterator 类实现 查找位置的方法 文本中的边界。的实例 BreakIterator 维护一个当前 定位并扫描文本返回 字符的索引,其中 边界出现。在内部, BreakIterator 使用 CharacterIterator,因此能够 扫描任何对象持有的文本 实现该协议。一种 StringCharacterIterator 用于 扫描传递给 setText 的 String 对象。
您使用提供的工厂方法 通过这个类来创建实例 各种类型的中断迭代器。在 特别是,使用 getWordIterator, getLineIterator,getSentenceIterator, 和 getCharacterIterator 创建 执行单词的 BreakIterators, 行、句子和字符边界 分别分析。一个 BreakIterator 只能在一个上工作 单位(单词、行、句子等 在)。您必须使用不同的迭代器 对于每个单元边界分析,您 希望表演。
线边界分析确定 什么时候可以破坏文本字符串 换行。机制正确 处理标点和连字符 单词。
句子边界分析允许 正确解释的选择 数字内的周期和 缩写和尾随 标点符号,例如引号 标记和括号。
字边界分析用于 搜索和替换功能,以及 与文本编辑应用程序一样 允许用户选择单词 双击。单词选择 提供正确的解释 标点符号在里面和后面 字。不属于的字符 一个词,例如符号或标点符号 标记,两边都有分词。
字符边界分析允许 用户与角色交互 他们期望,例如,当 在文本中移动光标 细绳。字符边界分析 提供正确的导航 字符串,不管如何 字符被存储。例如, 可能会存储重音字符 作为基本字符和变音符号 标记。用户认为是什么 字符可以不同 语言。
BreakIterator 旨在与 仅限自然语言。不使用 这个类来标记编程 语言。
【讨论】:
【讨论】:
只需使用正则表达式(\s+ - 它将应用于一个或多个空格(空格、制表符等))将字符串拆分为数组。
然后您可以遍历该数组并检查单词是否以.?! 结尾(String.endsWith() 以查找句子的结尾。
在保存任何单词之前,再次使用正则表达式删除每个非字母数字字符。
【讨论】:
当然,使用 StringTokenizer
import java.util.StringTokenizer;
public class Token {
public static void main(String[] args) {
String sentence = "Java! simple ?sentence parser.";
String separator = "!?.";
StringTokenizer st = new StringTokenizer( sentence, separator, true );
while ( st.hasMoreTokens() ) {
String token = st.nextToken();
if ( token.length() == 1 && separator.indexOf( token.charAt( 0 ) ) >= 0 ) {
System.out.println( "special char:" + token );
}
else {
System.out.println( "word :" + token );
}
}
}
}
【讨论】:
基于@Jarrod Roberson's answer,我创建了一个使用BreakIterator并返回句子列表的util方法。
public static List<String> tokenize(String text, String language, String country){
List<String> sentences = new ArrayList<String>();
Locale currentLocale = new Locale(language, country);
BreakIterator sentenceIterator = BreakIterator.getSentenceInstance(currentLocale);
sentenceIterator.setText(text);
int boundary = sentenceIterator.first();
int lastBoundary = 0;
while (boundary != BreakIterator.DONE) {
boundary = sentenceIterator.next();
if(boundary != BreakIterator.DONE){
sentences.add(text.substring(lastBoundary, boundary));
}
lastBoundary = boundary;
}
return sentences;
}
【讨论】: