2013-03-10 56 views
0

我正在嘗試創建單詞索引,從文本文件中讀取每行並檢查該單詞是否在該行中。如果是這樣,它會打印出號碼行並繼續檢查。在打印每個單詞和行號時,我已經掌握了它的工作方式,但我不確定可以使用哪種存儲系統來容納每個數字。創建單詞索引

代碼示例:

def index(filename, wordList): 
    'string, list(string) ==> string & int, returns an index of words with the line number\ 
    each word occurs in' 
    indexDict = {} 
    res = [] 
    infile = open(filename, 'r') 
    count = 0 
    line = infile.readline() 
    while line != '': 
     count += 1 
     for word in wordList: 
      if word in line: 
       #indexDict[word] = [count] 
       print(word, count) 
     line = infile.readline() 
    #return indexDict 

將打印出文字和任何計數的時間(行號),但我想要做的是存儲的號碼,這樣以後我可以做它打印出來

word linenumber 

word2 linenumber, linenumber 

等等。我覺得一本字典將工作,如果我把每行數的列表中,以便每個按鍵可以包含多個值,但我得到的最接近的是這樣的:

{'mortal': [30], 'dying': [9], 'ghastly': [82], 'ghost': [9], 'raven': [120], 'evil': [106], 'demon': [122]} 

當我想讓它顯示爲:

{'mortal': [30], 'dying': [9], 'ghastly': [82], 'ghost': [9], 'raven': [44, 53, 55, 64, 78, 97, 104, 111, 118, 120], 'evil': [99, 106], 'demon': [122]} 

任何想法?

+1

您可能需要一個默認爲默認爲[]的新鍵,並追加。當然,您的註釋行只是每次重寫一個單項列表的密鑰。 – geoffspear 2013-03-10 21:16:16

+0

對於每個回答的人,感謝您的意見。非常感謝。 – iKyriaki 2013-03-10 21:39:05

回答

2

你被這條線

indexDict[word] = [count] 

改變它取代了舊的價值

indexDict[word] = indexDict.setdefault(word, []) + [count] 

將產生你想要的答案。它會得到indexDict [word]的當前值,並將新的計數附加到它,如果沒有indexDict [word],它會創建一個新的空列表並向其追加計數。

+0

這實際上正是我所需要的。非常感謝你。 – iKyriaki 2013-03-10 21:39:32

+2

@iKyriaki:'defaultdict'解決方案以更簡潔的語法完成同樣的事情。 – 2013-03-10 21:45:54

+0

NP。你選擇字典,所以我使用字典的方法來幫助你。我不明白爲什麼有些人使用集合重寫你的代碼。 – octref 2013-03-10 21:46:42

3

嘗試這樣:

import collections 
def index(filename, wordList): 
    indexDict = collections.defaultdict(list) 
    with open(filename) as infile: 
     for (i, line) in enumerate(infile.readlines()): 
      for word in wordList: 
       if word in line: 
        indexDict[word].append(i+1) 
    return indexDict 

這將產生同樣的結果在您的示例(使用PoE的烏鴉)。

或者,您可能會考慮使用正常的dict而不是defaultdict並使用列表中的所有單詞進行初始化;以確保indexDict包含一個條目,即使對於不在文本中的單詞。

另外,請注意使用enumerate。這個內建函數對於迭代索引和某個列表的索引處的項目(如文件中的行)非常有用。

+1

對於行號,從1開始而不是零開始是有意義的。你可以用'enumerate(infile,1)'來做到這一點,然後再用'.append(i)' – 2013-03-10 21:26:01

2

有可能寫這個更Python的方式,但只是爲便於閱讀,你可以試試這個(一個簡單的例子):如果列表

dict = {1: [], 2: [], 3: []} 

list = [1,2,2,2,3,3] 

for k in dict.keys(): 
    for i in list: 
     if i == k: 
      dict[k].append(i) 


In [7]: dict 
Out[7]: {1: [1], 2: [2, 2, 2], 3: [3, 3]} 
+0

這會追加_lines_,而不是行號! – 2013-03-10 21:32:00

+0

我使用的數字只是爲了顯示邏輯,認爲已經有一個行索引值來追加 「count + = 1」。拉齊斯會消失。 – 2013-03-10 21:41:02

1

您需要將您的下一個項目添加到列表中,已經存在。

有名單已經在那裏了,即使是第一次,你找到一個詞最簡單的方法,就是用collections.defaultdict class來跟蹤你的話對線映射:

from collections import defaultdict 

def index(filename, wordList): 
    indexDict = defaultdict(list) 
    with open(filename, 'r') as infile: 
     for i, line in enumerate(infile): 
      for word in wordList: 
       if word in line: 
        indexDict[word].append(i) 
        print(word, i) 

    return indexDict 

我已經簡化你的代碼使用最佳實踐;將文件作爲上下文管理器打開,以便在完成後自動關閉,並使用enumerate()即時創建行號。

如果您將行變成一組字(set(line.split())也許,但不會刪除標點符號),那麼您可以加速一點點(並使其更加準確),因爲您可以使用set intersection對wordList(也是一套)進行測試,這可能會更快地找到匹配的單詞。

+0

你的'count'變量發生了什麼?應該htis:'indexDict [word] .append(count)'是這個'indexDict [word] .append(i)'?什麼是「res」? – hughdbrown 2013-03-10 22:00:53

+0

另外,如果你將成爲唯一提到'defaultdict'的人,你可能還會提到'collections.Counter',儘管我不明白OP的用例足以說明計數實例是否是想法。 – hughdbrown 2013-03-10 22:02:36

+0

編輯不當;感謝您指出這些錯誤。我考慮過提到'Counter',但駁回它;它的API對於這個用例來說是過分的。 – 2013-03-10 22:06:53