2013-03-10 83 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