迭代文本文件中的行,返回行号和出现次数?

时间:2014-01-11 08:41:39

标签: python string

我正在尝试编写这个代码,它可以充当索引的索引来筛选文本文件并返回字符串的出现以及它们所在的行。我越来越近了,但是我的迭代遇到了一个问题,我无法弄清楚要做什么。

def index(fileName, wordList):

    infile = open(fileName,'r')

    i = 0
    lineNumber = 0
    while True:
        for line in infile:
            lineNumber += 1
            if wordList[i] in line.split():
                print(wordList[i], lineNumber)
        i += 1
        lineNumber = 0

fileName = 'index.txt'
wordList = eval(input("Enter a list of words to search for: \n"))

index(fileName,wordList)

我用我的.txt文件填充了通用术语,所以它看起来像这样:

bird 
bird 
dog 
cat 
bird

当我提供字符串列表时,例如:

['bird','cat']

我得到以下输出:

Enter a list of words to search for: 
['bird','cat']
bird 1
bird 2
bird 5

所以它给了我列表中第一个字符串的术语和行号,但它没有继续下一个字符串。有什么建议?如果我可以优化输出以将行号包含在可以欣赏的单个打印中。

3 个答案:

答案 0 :(得分:4)

读取文件后,将更改当前文件位置。一旦文件位置到达文件末尾,读取文件将产生空字符串。

您需要使用file.seek来回放文件位置以重新读取文件。

但是,我宁愿按照以下方式(使用setin运算符)代替倒带:

def index(filename, words):
    with open(filename) as f:
        for line_number, line in enumerate(f, 1):
            word = line.strip()
            if word in words:
                print(word, line_number)

fileName = 'index.txt'
wordList = ['bird', 'cat'] # input().split()
words = set(wordList)
index(fileName, words)
  • eval执行任意表达式。而不是使用eval,如何使用input().split()

答案 1 :(得分:1)

因为当你到达文件末尾时,任何读取文件的尝试都会产生一个空字符串,你的程序就会失败。解决这个问题的一种方法是使用file.readlines并将这些行存储在列表中:

with open('test.txt') as f:
    wordInput = [input(), input()] #capture the input
    lines = f.readlines()
    for word in wordInput:
        counter = 0
        for line in lines:
            counter += 1
            if word in line:
                print(word, counter)

但是,对于大文件来说这有点效率低,因为它会将整个文件加载到内存中的缓冲区中。作为替代方案,您可以遍历这些行,然后在完成后调用file.seek(0)。这样,搜索就会回到文件的开头,你可以再次重新启动它。它的工作原理如下:

>>> with open('test.txt') as f:
        for line in f:
            print(line)
        f.seek(0)
        for line in f:
            print(line)


bird 

bird 

dog 

cat 

bird
0 #returns the current seek position
bird 

bird 

dog 

cat 

bird

另外,正如@falsetru在他的回答中提到的那样,避免使用eval(input),因为它会评估你放在那里的任何表达式,而这可能导致意外的输入问题。使用something个分隔值,然后执行wordList = input().split(something)

希望这有帮助!

答案 2 :(得分:0)

如果您尝试重复循环文件对象,则在第一个文件对象之后的任何尝试都将从文件末尾开始并立即停止。有几种方法可以解决这个问题;您可以将算法更改为在文件中单次传递,或者您可以将文件的内容保存到其他数据结构,然后分析该文件而不是文件,或者您可以使用infile.seek(0)返回到开头循环之间的文件。

相关问题