文本检索 关键词检索和_文本检索系统-3A:图书馆建设者

文本检索 关键词检索和

问候,

介绍

在我们开始设计和实现文本生成器类之前,我想

提Prometheuzz的回复:他有整个圣经的荷兰语版本

可用,包括那些奇特的书。 我下载了整个shebang,

入侵了我的King James文字处理器,现在我有两本圣经可供使用:

英文的“ King James”版本和荷兰的“ Staten Vertaling”版本。

荷兰语版本甚至比国王詹姆斯版还大,所以:-P

感谢Prometheuzz提供的那段有价值的文字; 我真的很感激。

在我已故的邻居中,荷兰语版本的矛盾较少(阅读:否)

德克的版本到处都是一团糟。 大部分原始解析文本麻烦

发生在Dirk的版本中。 只是进行了一些重写和快速黑客攻击

足以处理Prometheuzz提供的荷兰语版本。

LibraryBuilder

我们有工作要做:这又是LibraryBuilder界面:


public interface LibraryBuilder { 
    public void preProcess();
    public void postProcess(); 
    public void setTitle(String title); 
    public void buildGroup(String group);
    public void buildParagraph(String book, String chapter, int para, String text) throws IOException; 
    public Library build();
} 
AbstractBuilder类实现了所有此接口,并留下了一些

特定构建器将实现的抽象受保护方法,例如

KJBuilder(用于King James圣经版本)和SVBuilder(用于

Staten Vertaling版本)。

AbstractBuilder本身并不能完成所有工作,即它委托了很多

对于较小和较简单的建造者的工作。

这是所有这些的简单构建器:StringsBuilder:


class StringsBuilder extends ArrayList<String> { 
    private static final long serialVersionUID = 4709552086518644567L; 
    String[] build() { return this.toArray(new String[size()]); }
} 
它只是List <String>接口的一个实现,可以构建

给我们一个String []。 这就是全部。 请记住,图书馆本身只是

对整个文本使用一堆数组。 数组无法调整大小; 那是

我之所以喜欢构建器的原因之一,是那些操作更灵活但体积更大的建筑

数据结构(类),而最后生成所有数组。

这是另一个简单的构建器; 它建立了一个部分:


package text.builders; 
import text.library.Section; 
class SectionBuilder { 
    private String name;
    private int index;
    private int total; 
    SectionBuilder(String name, int index) { 
        this.name = name;
        this.index= index;
    } 
    void setTotal(int end) { this.total= end-index; } 
    String getName() { return name; } 
    Section build() { return new Section(name, index, total); }
} 
节可以是组中的节,书或章。 “索引”

成员指的是团体,书籍或

章节。 “总数”成员是该特定部分中的部分总数

数组。 另请参阅本文的上一部分,以获取各节的示例。

上面的代码可以构建一个Section。 下一个小的构建器将构建一个数组

我们的部分; 这里是:


class SectionsBuilder extends ArrayList<SectionBuilder> { 
    private static final long serialVersionUID = 1476840322184839715L; 
    boolean addSection(String name, int index, boolean add) { 
        int n= size();
        SectionBuilder s= (n == 0)?null:get(n-1); 
        if (add= (add || s == null || !s.getName().equals(name))) {
            add(new SectionBuilder(name, index));
            if (s != null) s.setTotal(index);
        }     
        return add;
    } 
    void postProcess(int total) { 
        if (size() > 0)
            get(size()-1).setTotal(total);
    } 
    Section[] build() {  
        int n= size();
        Section[] sections= new Section[n]; 
        for (int i= 0; i < n; i++)
            sections[i]= this.get(i).build(); 
        return sections;
    }
} 
SectionsBuilder是SectionBuilders的列表(不是不同的复数)。

当一个新的部分即将开始时,它会计算出多少个“事物”

在上一节中。 参见addSection()方法。 布尔值

无论如何,“ add”变量(如果为true)都会强制构建新的Section。

当此变量为false时,如果名称为

当前部分与前一个部分不同,或者

建造是所有这些的第一部分。

实际上,此构建器根本不跟踪Sections:它处理

SectionBuilders。 此构建器的build()方法将构建实际的Sections:

它在其列表中的每个SectionBuilder上调用build()方法,该方法依次

每个建立一个科。

间奏曲

让我们在此处暂停一分钟:我们可以构建单个Sections(使用

SectionBuilder),我们可以构建Sections的数组(使用SectionsBuilder)。

我们还可以使用StringsBuilder构建字符串数组。

但是我们还需要更多:我们需要知道单词出现在哪些段落中。 其他

单词(原文如此),我们需要在单个单词和列表中的索引列表之间建立映射

段落列表。 单个段落是代表以下内容的索引的字符串

再次是单个单词和标点符号。 (请参阅上一篇文章

有关如何压缩段落的部分)。

还有更多工作要做...

更多建设者

这是一个WordBuilder; 它会跟踪其中一个单词的段落编号

发生。 不过,它不在乎哪个词。 已经找到了某个地方

其他。 它确实知道它是整个文本中的第“ index”个词。 这是

实现:


class WordBuilder { 
    private int index;
    private List<Integer> paragraphs= new ArrayList<Integer>(); 
    WordBuilder(int paragraph) { 
        this.index= paragraph;
    } 
    int getIndex() { return index; } 
    void addParagraph(int paragraph) { paragraphs.add(paragraph); } 
    int[] build() { 
        int n= paragraphs.size();
        int array[]= new int[n]; 
        for (int i= 0; i < n; i++) array[i]= paragraphs.get(i); 
        return array;
    }
} 
它基本上会跟踪此特定段落的列表编号列表

单词出现,它可以建立一个整数数组,这些段落的索引

在这个词再次出现。 火箭科学不是特别重要。

最后一个生成器将单词映射到WordBuilders。 毫不奇怪

该生成器名为WordMapBuilder; 这里是:


class WordMapBuilder extends HashMap<String, WordBuilder> { 
    private static final long serialVersionUID = -5282145470567550534L; 
    WordMap build() { 
        WordMap map= new WordMap(); 
        for (Map.Entry<String, WordBuilder> entry : entrySet()) 
            map.put(entry.getKey(), entry.getValue().build()); 
        return map;
    }
} 
它将一个单词(一个字符串)映射到一个WordBuilder(见上文),它可以产生

WordMap。 稍后我们会看到它,但我想您可以猜测是什么:它

将字符串(单词)映射到Integer [],这是其中

单词出现。

抽象生成器

现在我们有了实现LibraryBuilder的组成部分,让我们来看看

此实现的全部意义。 该类是一个抽象类,因为

它为扩展类留下了一些简单的方法:


protected abstract String clean(String book, String chapter, 
                int paragraph, String text);
protected abstract Collection<String> getNoise(); 
第一种方法应该清除段落文本。 大部分是

已经以一般方式清理了,但是特定的构建器可能需要清理

文字甚至更多。

在德克(Dirk)的国王詹姆斯(King James)版本中,某些词带有花括号,而另一些则带有

大括号周围。 我不需要那些花括号,所以我的KJBuilder的clean()

方法实现如下所示:


protected String clean(String book, String chapter, 
            int paragraph, String text) { 
    text= text.replaceAll("[({\\[\\]})]", ""); 
    return text.replaceAll("[^\\x20-\\x7e]", "");
} 
我通过删除所有非7位ASCII字符来进一步清理文本

文字中的内容(还记得第一篇文章顶部带有点的那些“ y”吗?

这摆脱了他们)。

第二种方法应该返回一个不是

应该被索引。 想想诸如“ the”,“ a”,“ is”之类的词。

AbstractBuilder完成了所有工作,只需要知道*哪些词是

应该从WordMap中排除(请参见上文)。

这是KJBuilder(扩展AbstractBuilder)返回其干扰词的方式:


private static final Set<String> noise= new HashSet<String>(); 
static { 
    noise.addAll(Arrays.asList(new String[] { 
        "O", "s",
        "The", "the", 
        "A", "a", "An", "an", 
        "Of", "of", "By", "by", "On", "on",
        "Am", "am", "Are", "are", "Is", "is", "Be", "be",
        "Had", "had", "Has", "has", "Have", "have",
        "At", "at", "As", "as", "In", "in", 
        "Do", "do", 
    }));
} 
protected Collection<String> getNoise() { 
    return noise;
} 
HashSet是一个Set,而Set是一个Collection。 Arrays.asList()方法可以

从数组中构建一个列表,集合可以接受一个列表,该列表也是

集合作为构造函数参数,最终由返回

getNoise()方法。

今天已经足够打字了。 我去给自己喝杯咖啡。 我希望看到

您将在本文下面的下一部分中找到您。

亲切的问候,

乔斯

B部分

翻译自: https://bytes.com/topic/java/insights/681150-text-retrieval-systems-3a-library-builder

文本检索 关键词检索和

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值