问候,
介绍上周,我开始考虑使用文本处理工具。 我已经找到
大量文字:圣经的英王钦定版。 我要去
使用该文本作为本文中的示例。
我想将整个文本“转换”为一个Java对象,使我可以搜索
以一种非常强大的方式浏览整个文本。 当然那个对象一定是
可持久(读取:可写到磁盘,可从磁盘读取)。 我不打算
为它建立一个视图; 我把它留给你练习。
我确实实现了这个对象; 我称其为“图书馆”和搜索工具,
我称之为“查询”。 图书馆必须以小组,书籍,章节和
段落以分层方式。
组具有标题文本和存储书籍。 书籍也有标题和存储
章节; 同样,章节具有标题和存储段落。
段落是一段文本,通常由一个或多个句子组成。
我希望能够找到单词,单词的组合或其中的一部分
paragrahs。 结果应该是可以操纵的段落列表
进一步显示给用户。
最重要的是,我希望用户能够向其中添加“注释”或“注释”
段落。 注释是无法搜索的简单文本
本身(否则,它们本来应该是书本的一部分)。
栏目细分为组,书籍和章节只是部分列表。
这是一个Section类:
public class Section implements Serializable {
private static final long serialVersionUID = 2396474693631832475L;
private String name;
private int index;
private int total;
public Section(String name, int index, int total) {
this.name = name;
this.index= index;
this.total= total;
}
public String getName() { return name; }
public int getIndex() { return index; }
public int getTotal() { return total; }
}
一节可以用于例如书籍,例如,一节可以描述书籍
创世记(这是本节的名称)。 “索引”和“总计”值
指书籍的细分,在示例中,索引指清单
其中章节“索引”是所代表的书籍的第一章
通过本节。 “总”值是书中章节的总数。
节也可以用于组,例如在King James示例中有
三组部分:旧约,新约和启示录
图书。 旧约部分的“索引”值是第一部分的索引
旧约中的一本书(恰好是无神论者的创世纪
在我们之间)。 “总计”值等于39,因为其中有39本书
旧约。
我敢肯定,您可以确定一个Section可以同样适用于所有
一本书中的章节。 所以我需要三个节的列表或数组,一个
一组,一本书,一章。
章节章节的“索引”和“总计”值指的是段落
在图书馆的所有章节,书籍和小组中。
这是一个小例子:
假设有两个小组,每个小组有两本书。 还假设
前两本书分为3章和6章。 中有两段
第一本书的第一章,第二本书的三段,以及
第一本书的第三章。 以下ASCII艺术图形可能会阐明
小组,书籍和章节的章节如何组织:(没关系
行号)
+---+---+
|2 |2 | <-- groups
+--|+--|+
| |
| +---+
| |
v v
+---+---+---+---+ +---+
|3 |6 | | | ... | b | <-- books
+--|+---+---+---+ +---+
|
|
v
+---+---+---+---+---+---+ +---+
|2 |3 |3 | | | | ... | c | <-- chapters
+--|+--|+--|+---+---+---+ +---+
| | |
| | +-----------+
| +---+ |
| | |
v v v
+---+---+---+---+---+---+---+---+ +---+
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ... | p | <-- paragraphs
+- -+---+---+---+---+---+---+---+ +---+
段落和文字压缩
文本检索系统中的段落都存储在一个简单的数组中
弦乐 它们在“章节”章节中有所提及(请参见上文)。 在里面
在本文的前一部分,我说过,我不希望数据中的数据部分
系统要大于原始文本(以字节为单位)。 这是任意的
我想遇到的限制。
给定Section对象的那些数组,我们需要压缩实际的文本本身。
在普通对话,文章或小说中,最多不超过20,000
*使用*不同的*词,包括词缀和变位
词干,例如“工作中”,“工作中”,“工作中”,“工作中”或“魔鬼”,
恶魔 为方便起见,我将它们全部视为不同的词。
我什至将一个单词的所有格(“可能形式”)视为两个单独的单词,
如:“上帝的方式”。 该片段中包含三个单词:“上帝”,“ s”和“道路”。
单词仅包含字母和/或数字; 它不包含任何标点符号
字符或空格。 空格只是分隔单词,就像这些标点符号一样
人物呢。
经过一些预处理,根据我对单词的草率定义,
我发现这本圣经的国王詹姆斯版只包含15267
不同的词 该计数包括所有这些不同的名称和首字母
以及大写和小写字母(例如“ the”和“ The”)。
根据“ wc”(单词计数,unix实用程序),国王詹姆斯圣经包含
989006个单词,因此平均每个单词出现大约989006/15267 = 63.8次。
当您想到它时,单词以空格或标点符号结尾。
标点符号后面是否有空格。 所以我可以放心
忽略空格(它们在单词和标点符号之间是隐含的)。
以这部分句子为例:
“看哪,我照你的意愿代了上帝。”
我在要处理的每个标记周围放置了方括号,并删除了空格:
[看] [,] [i] [am] [根据] [到] [你的] [愿望] [in] [上帝] ['] [s] [代替] [。]
请注意,逗号在概念上右边有一个空格。 单
引号字符,在此示例中,尾随点没有空格
跟随它的字符。
我需要两种类型的标点符号:一种带有以下空格,另一种
没有空格字符。 那我可以忽略所有空格。 所以一个字就是
后跟一个标点符号(任何类型)或一个空格字符。
我只考虑一个空格字符,即没有多个空格,也没有制表符
字符或任何其他类似空格的字符。
考虑以下段落:
“这是一个句子。这也是一个句子。”
上面描述的方法将该段分为以下部分:
[这个] [是] [a] [句子] [。] [这个] [是] [a] [句子] [as] [井] [。]
假设有一个唯一词列表:
- 0x100:此
- 0x101:是
- 0x102:a
- 0x103:句子
- 0x104:为
- 0x105:很好
还要假设有两个标点符号列表。 第一名单
存储标点符号,并在其后隐含一个空格; 第二个清单
仅存储标点符号:
- 0x000 :。
- 0x080 :。
上段可以表示为列表索引值的序列:
0x100 0x101 0x102 0x103 0x000 0x100 0x101 0x102 0x103 0x104 0x105 0x080
我刚才做的是:代码点[0x000,0x020)保留给
标点符号,后跟一个空格。 代码点
[0x080,0xa0)保留给标点符号,后跟一个
空格字符。 所有其他数字[0x0100,0x10000)保留为整个
话。 这意味着我只能存储2 ^ 16-256个不同的单词。 这是
没有限制(圣经只包含15267个不同的词)。
在Java中,字符串由零个或多个字符组成。 字符(“字符”)
是一个16位无符号数字。 我可以(ab)使用这些字符作为索引
数字; 结果段落可以是Java字符串,其中字符串包含
只是那些索引值。
上面的示例段落在String中只需要12个字符,而不是
原始字符串中的48个字符。 那肯定会有助于压缩
整个。
继续,我将如下使用(ab)使用字符值:
- 0x0000-0x001f:标点符号,其右边带有空格;
- 0x0080-0x009f:单标点字符;
- 0x0100-0xffff:单词列表中的索引。
如果单词后没有任何标点字符代码,则为空格字符
假设。 单词只是Character.isLetter()的非空序列
或Character.isDigit()方法认为是正确的。
请注意,字符值[0x0020,0x007f]和[0x00a0,0x00ff]不是
用过的; 就这样吧。 另请注意,我转换了
标点符号到组成“ ISO控制字符”的范围
根据Java的Character.isISOControl()方法。
我希望在本文的下一部分看到您。 我会告诉你
我设计并实现了文本处理系统的“处理器”部分。
亲切的问候,
乔斯
B部分From: https://bytes.com/topic/java/insights/676456-text-retrieval-systems-2a-text-processors