2012-10-27 49 views
0

我有大約1500個文檔的集合。我通過每個文檔解析並提取令牌。這些令牌存儲在散列表(作爲關鍵字)中,並且它們在集合中出現的總次數(即頻率)被存儲爲值。構建Java邏輯中的倒排索引

我必須擴展它來構建倒排索引。也就是說,術語(key)|它發生的文件數量 - > DocNo |該文件中的頻率。對於exmple,

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 
     } 
    } 
} 

我必須建立在這個代碼。我無法真正想到實現倒排索引的好方法。到目前爲止,我認爲有價值的二維數組。所以這個術語是關鍵,價值(即二維數組)將存儲docId和termFreq。

請讓我知道我的邏輯是否正確。

+1

我不明白你想要做什麼。什麼是DocFreq,DocNum和TermFreq?什麼應該是你的倒排索引的關鍵和價值? –

+0

我有一個文件集合。我解析每個文檔並提取每個單詞。現在對於每個單詞,我必須存儲/計算以下信息: 術語(即單詞),DocFreq(此特定單詞的文檔數量發生) - > DocNum和TermFreq(文檔ID和出現頻率在那份文件中)。 因此,例如,「數據」一詞出現在3(DocFreq)文檔中。這3個文件是1,23,100(DocNum),在DocNum 1'數據'出現12次(TermFreq),DocNum 23'數據'出現31次,而DocNum 100'數據'出現17次。 – aquafatz

回答

1

我認爲最好有兩種結構:Map<docnum, Map<term,termFreq>>Map<term, Set<docnum>>。您的docFreqs可以在第二張地圖的值中作爲set.size讀取。該解決方案不包含自定義類,並且可以快速檢索所需的所有內容。

第一張地圖包含所有信息,第二張地圖包含允許按術語快速查找的派生項。處理文檔時,填寫第一張地圖。之後您可以派生出第二張地圖,但一次傳遞也很容易。

+0

謝謝!這真的簡化了事情。 我創建了第一個地圖,Map >。 但我如何製作第二張地圖呢? – aquafatz

+0

那麼,對於在文檔中遇到的每個術語,只需將該文檔添加到該術語的密鑰下的集合。它與您已經用於更新termFreq的邏輯類型相同。由於您正在使用'Set ',重複項將被自動拒絕。 –

+0

明白了!謝謝!! – aquafatz

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()方法將簡單地遞增爲出現的總次數的計數器,和將插入或更新出現在internam地圖的數量。

+0

這太好了。但我對hashmaps很陌生,我從來沒有將對象當作價值觀來使用。如果可能的話,你能解釋一下嗎? 謝謝! – aquafatz

+0

HashMap只能有對象作爲值。將存儲的TermFrequencies實例存儲爲HashMap中的值與存儲String或Integer實例無異。你有什麼問題? –

0

我曾經實施過你所要求的。你的方法存在的問題是它不夠抽象。您應該使用對象爲術語,文檔及其關係建模。在第一次運行時,創建術語索引和文檔對象,並在填充術語索引時迭代文檔中的所有術語。之後,您可以在內存中表示您可以輕鬆轉換爲所需的輸出。 不要以面向對象的語言思考2d數組。除非你想解決數學問題或優化某些東西,否則大部分時間都不是正確的方法。

+0

雅..這似乎是JB解釋,是嗎? 謝謝! – aquafatz

0

我不知道這是否仍是一個熱點問題,但我會建議你做這樣的:

您運行在您的所有文件,並給他們增加訂單的ID。對於每個文檔,您都會運行所有單詞。

現在您已經有了一個將字符串(您的詞)映射到DocTermObjects數組的Hashmap。DocTermObject包含docId和TermFrequency。

現在對於文檔中的每個單詞,如果它不包含您創建它的DocTermObjects數組,則在HashMap中查找它,否則只查看它的最後一個元素(由於運行時這很重要,想想吧)。如果此元素具有您此刻處理的文檔,則可以增加TermFrequency。否則,或者如果數組爲空,則用您的實際docId添加一個新的DocTermObject,並將TermFrequency設置爲1.

稍後,您可以使用此數據結構計算得分例如。您當然也可以將這些分數保存在DoctermObjects中。

希望它有幫助:)