文本检索系统-3B:库生成器

问候,

欢迎回来; 让我们继续执行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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值