3

我正在做一个项目来从大量文本文件中解析出唯一的单词。我已经完成了文件处理,但我正在尝试改进解析过程。每个文件都有一个特定的文本段,以我在实时系统上使用正则表达式捕获的某些短语结尾。

解析器应该遍历每一行,并根据 3 个标准检查每个单词:

  1. 超过两个字符
  2. 不在预定义的字典集中dict_file
  3. 尚未在单词列表中

.writerow(foo)结果应该是一个二维数组,每行是每个文件的唯一单词列表,在处理每个文件后使用该方法将其写入 CSV 文件。

我的工作代码在下面,但它很慢而且很笨拙,我错过了什么?

我的生产系统运行 2.5.1,只有默认模块(所以 NLTK 是不行的),不能升级到 2.7+。

def process(line):
    line_strip = line.strip()
    return line_strip.translate(punct, string.punctuation)

# Directory walking and initialization here
report_set = set()
with open(fullpath, 'r') as report:
    for line in report:
        # Strip out the CR/LF and punctuation from the input line
        line_check = process(line)
        if line_check == "FOOTNOTES":
            break
        for word in line_check.split():
            word_check = word.lower()
            if ((word_check not in report_set) and (word_check not in dict_file) 
                 and (len(word) > 2)):
                report_set.append(word_check)
report_list = list(report_set)

编辑:根据 steveha 的建议更新了我的代码。

4

2 回答 2

3

一个问题是in对 a 的测试list很慢。您可能应该保留 aset以跟踪您看到的单词,因为ina 的测试set非常快。

例子:

report_set = set()
for line in report:
    for word in line.split():
        if we_want_to_keep_word(word):
            report_set.add(word)

然后当你完成时:report_list = list(report_set)

任何时候你需要强制 aset进入 a list,你都可以。但是,如果您只需要循环或进行in测试,则可以将其保留为set; 这是合法的for x in report_set:

另一个可能或可能无关紧要的问题是,您使用该.readlines()方法一次性从文件中删除所有行。对于非常大的文件,最好只使用打开的文件句柄对象作为迭代器,如下所示:

with open("filename", "r") as f:
    for line in f:
        ... # process each line here

一个大问题是我什至看不到这段代码是如何工作的:

while 1:
    lines = report.readlines()
    if not lines:
        break

这将永远循环。第一条语句用 slurps 所有输入行.readlines(),然后我们再次循环,然后下一次调用.readlines()已经report用尽,所以调用.readlines()返回一个空列表,它会跳出无限循环。但是现在这已经丢失了我们刚刚阅读的所有行,其余代码必须使用一个空lines变量。这甚至是如何工作的?

因此,摆脱整个while 1循环,并将下一个循环更改为for line in report:.

此外,您实际上并不需要保留count变量。您可以随时使用len(report_set)来找出set.

此外,使用 aset您实际上不需要检查一个单词是否是in集合;您可以随时调用report_set.add(word),如果它已经在其中set,则不会再次添加!

此外,您不必按照的方式进行操作,但我喜欢制作一个可以完成所有处理的生成器。剥离线,翻译线,在空白处分割,并产生准备使用的单词。我也会强制单词小写,除非我不知道FOOTNOTES仅以大写形式检测是否重要。

因此,将以上所有内容放在一起,您会得到:

def words(file_object):
    for line in file_object:
        line = line.strip().translate(None, string.punctuation)
        for word in line.split():
            yield word

report_set = set()
with open(fullpath, 'r') as report:
    for word in words(report):
        if word == "FOOTNOTES":
            break
        word = word.lower()
        if len(word) > 2 and word not in dict_file:
            report_set.add(word)

print("Words in report_set: %d" % len(report_set))
于 2012-06-20T01:09:01.530 回答
2

尝试用字典或集合替换 report_list。如果 report_list 是列表,则 word_check 不在 report_list 中运行缓慢

于 2012-06-20T01:08:57.380 回答