0

我收集了大约 1500 个文档。我解析了每个文档并提取了标记。这些标记存储在哈希图中(作为键),它们在集合中出现的总次数(即频率)存储为值。

我必须扩展它来建立一个倒排索引。也就是说,术语(键)| 它出现的文档数-->DocNo|该文档中的频率。例如,

    Term       DocFreq    DocNum      TermFreq  
  data           3           1            12  
                            23            31  
                            100           17  
  customer       2          22            43  
                            19            2  

目前,我在 Java 中有以下内容,

hashmap<string,integer>  
for(each document)  
{  
    extract line  
    for(each line)  
    {  
        extract word   
        for(each word)  
        {  
            perform some operations  
            get value for word from hashmap and increment by one  
        }  
    }  
}  

我必须建立在这段代码上。我真的想不出实现倒排索引的好方法。到目前为止,我想将 value 设为 2D 数组。所以术语将是键,值(即二维数组)将存储 docId 和 termFreq。

请让我知道我的逻辑是否正确。

4

4 回答 4

3

我会使用Map<String, TermFrequencies>. 此映射将为找到的每个术语维护一个 TermFrequencies 对象。TermFrequencies 对象将具有以下方法:

void addOccurrence(String documentId);
int getTotalNumberOfOccurrences();
Set<String> getDocumentIds();
int getNumberOfOccurrencesInDocument(String documentId);

它将在Map<String, Integer>内部使用 a 将术语出现的每个文档与该术语在文档中的出现次数相关联。

该算法将非常简单:

for(each document) {  
    extract line  
    for(each line) {  
        extract word   
        for(each word) {  
            TermFrequencies termFrequencies = map.get(word);
            if (termFrequencies == null) {
                termFrequencies = new TermFrequencies(word);
            }
            termFrequencies.addOccurrence(document);
        }  
    }  
}  

addOccurrence()方法将简单地为出现的总数增加一个计数器,并在内部映射中插入或更新出现的数量。

于 2012-10-27T16:46:53.013 回答
2

我认为最好有两种结构: aMap<docnum, Map<term,termFreq>>和 a Map<term, Set<docnum>>。您的 docFreqs 可以像set.size第二张地图的值一样被读取。该解决方案不涉及自定义类,并允许快速检索所需的一切。

第一张地图包含所有信息,第二张地图是一个衍生品,允许按术语快速查找。在处理文档时,您填写了第一张地图。您可以在之后导出第二张地图,但也很容易一次性完成。

于 2012-10-27T16:45:09.787 回答
0

我曾经实现了您的要求。您的方法的问题在于它不够抽象。您应该使用对象对术语、文档及其关系进行建模。在第一次运行中,创建术语索引和文档对象,并在填充术语索引时迭代文档中的所有术语。之后,您在内存中有一个表示,您可以轻松地将其转换为所需的输出。不要从考虑面向对象语言中的二维数组开始。除非您想解决数学问题或优化某些东西,否则大多数时候这不是正确的方法。

于 2012-10-27T16:48:29.727 回答
0

我不知道这是否仍然是一个热门问题,但我建议你这样做:

您检查所有文件并按递增顺序给它们一个 id。对于每个文档,您都会遍历所有单词。

现在您有了一个 Hashmap,它将字符串(您的单词)映射到一个 DocTermObjects 数组。DocTermObject 包含一个 docId 和一个 TermFrequency。

现在对于文档中的每个单词,您在 HashMap 中查找它,如果它不包含创建它的 DocTermObjects 数组,否则您只查看它的最后一个元素(由于运行时这很重要,请考虑一下)。如果此元素具有您当前处理的 docId,则增加 TermFrequency。否则,或者如果 Array 为空,则使用您的实际 docId 添加一个新的 DocTermObject 并将 TermFrequency 设置为 1。

例如,稍后您可以使用此数据结构来计算分数。当然,您也可以将分数保存在 DoctermObjects 中。

希望它有所帮助:)

于 2013-03-12T13:50:58.637 回答