问候,
欢迎回来; 让我们继续执行AbstractBuilder类。
AbstractBuilder实现这是AbstractBuilder的数据部分:
protected String title;
protected WordMapBuilder wordMap = new WordMapBuilder();
protected SectionsBuilder groups = new SectionsBuilder();
protected SectionsBuilder books = new SectionsBuilder();
protected SectionsBuilder chapters = new SectionsBuilder();
protected StringsBuilder paragraphs= new StringsBuilder();
protected StringsBuilder words = new StringsBuilder();
protected String[] punctuation = { "", "" };
字符串标题和几个构建器不需要任何进一步的解释。
String []标点仅存储两个字符串。 每个字符
字符串是输入到AbstractBuilder的文本中的标点符号
宾语。 第一个字符串包含标点符号,后跟一个
空间; 第二个字符串包含标点符号,后面没有
空间。 AbstractBuilder将新的标点符号添加到每个
需要时使用字符串。
回想一下单词只存储一次; 对于段落中的每个单词
它的索引存储在列表中。 索引值从0x0100开始(请参阅上一个
本文的一部分)。 因此,如果单词存储在列表中的位置“ i”,
它的索引等于“ i + 0x0100”。 这些索引值完全是合法字符,
因此段落可以存储在字符串中。
以下方法使用上述概念:
private char getWord(String word) throws IOException {
WordBuilder w= wordMap.get(word);
int i;
if (w == null) {
if ((i= words.size()+0x100) > 0xffff)
throw new LibException("too many different words");
wordMap.put(word, w= new WordBuilder(i));
words.add(word);
}
else
i= w.getIndex();
w.addParagraph(paragraphs.size());
return (char)i;
}
该方法尝试在wordMap中查找单词;
如果找不到,并且
wordMap已包含最大数量的唯一单词,该方法失败。
否则,新的WordBuilder及其新索引将存储在地图中。
如果找到了单词,则从找到的WordBuilder中检索其索引。
最后是段落编号(这是当前要馈入的段落
(AbstractBuilder))添加到WordBuilder。 使用此私有方法
通过文本压缩方法。
这是已实现的LibBuilder接口中的前几种方法。
他们是微不足道的:
public void preProcess() { }
public void setTitle(String title) { this.title= title; }
public void buildGroup(String group) {
groups.addSection(group, books.size(), false);
}
AbstractBuilder不需要预处理;
如果扩展类确实
需要预处理当然可以重写此方法。
下一个方法基本上完成了所有工作:它接收一段文本
并且必须处理它。 这里是:
public void buildParagraph(String book, String chapter, int paragraph, String text) throws IOException {
boolean add= books.addSection(book, chapters.size(), false);
chapters.addSection(chapter, paragraphs.size(), add);
text= normalizeSpace(text);
text= normalizeControl(text);
text= clean(book, chapter, paragraph, text);
text= normalizePunctuation(text);
text= compress(text);
paragraphs.add(text);
}
首先,将书添加到书SectionsBuilder中;
如果书名是
同样,不添加任何新书,该方法返回false; 否则的方法
返回true,表示已添加一本新书。 如果是这样,则需要新的章节
无论如何都要添加。 您会看到所有发生在前两行
该方法。
其他各行一点一点地清除了段落文本:第一个相邻的空格
在所有其他可能的空格字符之后被“标准化”到单个空格
已转换为ASCII空格字符(代码点== 0x0020)。
接下来,所有控制字符都将从段落文本中删除(例如^ Z)。
clean()方法需要由扩展类实现。 我们已经看到
本文前面部分中的示例。 normalizePunctuation()
该方法要注意上述的标点符号。
compress方法压缩段落文本。 这里是:
protected boolean isLetter(int c) {
return Character.isLetter(c) || Character.isDigit(c);
}
protected String compress(String text) throws IOException {
StringBuilder sb= new StringBuilder();
StringBuilder wb= new StringBuilder();
for (int i= 0, n= text.length(); i < n; i++) {
char c= text.charAt(i);
if (isLetter(c))
wb.append(c);
else {
if (wb.length() > 0) {
sb.append(this.getWord(wb.toString()));
wb.setLength(0);
}
if (c == ' ') continue;
sb.append(c);
if (c < ' ') i++;
}
}
if (wb.length() > 0)
sb.append(this.getWord(wb.toString()));
return sb.toString();
}
此方法的参数是段落文本,可以很好地清除。
的
方法使用另一个简单的方法:isLetter()。 此方法确定哪个
字符应视为字母。 Unicode中的任何字母设置为
以及Unicode集中的任何数字在本段中均视为字母
文本。
compress方法必须处理字母,空格和标点符号
已经转换为0x0000、0x001f范围内的字符
标点符号,后跟一个空格,范围为0x0080、0x009f
标点符号,后面不能有空格。
如果找到一个单词,则在wordMap中查找其索引,并且索引为
附加到压缩的字符串。 标点符号原样追加
到压缩的字符串。 只是简单地忽略了空格。 如果段落以
一个单词,最后一次检查将找到它,并将该单词的索引附加到
再次压缩String。
最后,返回压缩的段落String并将其追加
到段落字符串列表。
当所有段落文本均已馈入AbstractBuilder后,
处理需要完成:小组,书籍和
章节尚不知道不会再添加任何项目,即它们的
需要设置“ total”成员变量。 这是这样做的:
public void postProcess() {
groups.postProcess(books.size());
books.postProcess(chapters.size());
chapters.postProcess(paragraphs.size());
removeNoise();
}
通过以下方式调用SectionsBuilders的postProcess()方法(请参见上文)
正确的值。 最后,将干扰词从wordMap中删除。
这是实现:
private void removeNoise() {
Collection<String> noise= getNoise();
if (noise != null)
for (String word : noise)
wordMap.remove(word);
}
此方法向其子类询问字符串集合。
如果收藏
存在时,集合中的所有单词都将从wordMap中删除。 注意
删除了两个键,值对,因此包含
单词的索引列表也将被删除。
在后处理之后,可以要求构建者构建最终结果; 我们想要
图书馆; 这是接口的build()实现:
public Library build() {
return new Library(title,
wordMap.build(),
groups.build(),
books.build(),
chapters.build(),
paragraphs.build(),
words.build(),
punctuation);
}
所有嵌入式构建器都被要求build()他们的结果;
一切都是
传递给将构造其成员变量的Library构造函数。
标题字符串和标点字符串也都被传递。
结束语在上一篇文章中,我们构建了读取原始文本的处理器
并将段落提供给LibraryBuilder。 文章的这一部分
这种LibraryBuilder的实现。 这样的建设者可以产生
图书馆。 这样一个图书馆的实施将是
本文的下一部分。
库是包含完整文本的可序列化对象。 图书馆
本身只能复制文本的一部分。 它可以复制整个
书籍文字或书籍中的单个章节。 它也有能力
产生“书签”,这是通向“更智能”文本的桥梁
检索方法:查询。 查询是的最后部分的主题
本文。
我希望您能走到这一步,这是很多阅读和理解的内容
这是全部的结构,我也希望下周再见。
亲切的问候,
乔斯
From: https://bytes.com/topic/java/insights/739673-text-retrieval-systems-3b-library-builder