在Java逻辑中构建反向索引

时间:2012-10-27 15:58:54

标签: java indexing hashmap

我收集了大约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  
        }  
    }  
}  

我必须以此代码为基础。我真的不能想到一个实现倒排索引的好方法。 到目前为止,我想过将值设为2D数组。因此,该术语将成为关键,而值(即2D数组)将存储docId和termFreq。

如果我的逻辑是正确的,请告诉我。

4 个答案:

答案 0 :(得分:3)

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

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

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

算法非常简单:

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()方法只会增加一个计数器的总出现次数,并会插入或更新国际地图中的出现次数。

答案 1 :(得分:1)

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

第一个地图包含所有信息,第二个地图是允许按术语快速查找的衍生物。在处理文档时,您将填充第一张地图。您可以在之后派生第二张地图,但也可以一次性完成。

答案 2 :(得分:0)

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

答案 3 :(得分:0)

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

您将遍历所有文档,并按递增顺序为其提供ID。对于每个文档,您运行所有单词。

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

现在对于文档中的每个单词,你可以在HashMap中查找它,如果它不包含你创建它的DocTermObjects数组,那么你只看它的非常LAST元素(这很重要,因为运行时,想一想)。如果此元素具有您当前处理的docId,则会增加TermFrequency。否则,如果Array为空,则使用实际的docId添加新的DocTermObject,并将TermFrequency设置为1.

稍后您可以使用此数据结构来计算分数。你也可以在DoctermObjects中保存得分。

希望它有所帮助:)