我在搜索一个很大的列表时遇到了速度问题。我有一个文件,里面有很多错误和非常奇怪的单词。我正试图使用difflib在一个包含650000个单词的字典文件中找到最接近的匹配项。下面的方法工作得很好,但是非常慢,我想知道是否有更好的方法来解决这个问题。这是代码:
from difflib import SequenceMatcher
headWordList = [ #This is a list of 650,000 words]
openFile = open("sentences.txt","r")
for line in openFile:
sentenceList.append[line]
percentage = 0
count = 0
for y in sentenceList:
if y not in headwordList:
for x in headwordList:
m = SequenceMatcher(None, y.lower(), x)
if m.ratio() > percentage:
percentage = m.ratio()
word = x
if percentage > 0.86:
sentenceList[count] = word
count=count+1
感谢你的帮助,软件工程甚至还没有接近我的强项。非常感谢。
您应该将
headwordList
更改为set
。测试将非常缓慢。它必须对
headwordList
中的每个单词进行字符串比较,一次一个单词。这将花费与列表长度成比例的时间;如果将列表长度加倍,则将花费双倍的时间进行测试(平均)。对于
set
,执行in
测试所需的时间总是相同的;它不依赖于set
中元素的数量。所以这将是一个巨大的加速。现在,整个循环可以简化为:
所有这些都是从
headwordList
中找到比率最高的单词,并保留它(但只有当比率超过0.86时才保留它)。这是一个更快的方法。我要把名字headwordList
改成headwords
,因为我希望你把它变成set
,而不是list
。这看起来有点棘手,但在Python中这是最快的方法。我们将调用内置的
max()
函数来查找具有最高比率的SequenceMatcher
结果。首先,我们构建一个“生成器表达式”,尝试headwords
中的所有单词,对每个单词调用SequenceMatcher()
。但当我们结束的时候,我们也想知道这个词是什么。因此,生成器表达式生成元组,元组中的第一个值是SequenceMatcher
结果,第二个值是单词。max()
函数不知道我们关心的是比率,所以我们必须告诉它;我们通过制作一个函数来测试我们关心的东西,然后将该函数作为key=
参数传递。现在max()
为我们找到比率最高的值。max()
使用生成器表达式生成的所有值并返回单个值,然后将其解压到变量m
和word
。在Python中,最好使用像
sentence_list
这样的变量名,而不是sentenceList
。请参阅以下指南:http://www.python.org/dev/peps/pep-0008/使用递增索引变量并将其分配到列表中的索引位置是不好的做法。相反,从空列表开始,使用
.append()
方法函数附加值。另外,你可能会做得更好,建立一个字典的单词和他们的比率。
注意,您的原始代码似乎有一个错误:只要任何单词的百分比超过0.86,所有单词都将保存在
sentenceList
中,不管它们的比率是多少。上面我写的代码只保存了单词本身的比例足够高的单词。编辑:这是为了回答一个关于需要用括号括起来的生成器表达式的问题。
每当我收到错误消息时,我通常会将生成器表达式单独拆分并将其分配给一个变量。像这样:
这就是我的建议。但是,如果您不介意复杂的行看起来更加繁忙,您只需按照错误消息的建议添加一对额外的圆括号,这样生成器表达式就完全用圆括号括起来了。就像这样:
Python允许在将表达式传递给函数时省略生成器表达式周围的显式括号,但前提是该表达式是该函数的唯一参数。由于我们还传递一个
key=
参数,因此需要一个完全带圆括号的生成器表达式。但我认为如果你把genexp单独分出来,阅读起来会更容易。
编辑:@Peter Wood指出,文档建议重用
SequenceMatcher
来提高速度。我没有时间测试,但我认为这是正确的方法。幸运的是,代码变得更简单了!总是个好兆头。
编辑:我刚刚测试了代码。这个代码对我有效;看看它是否对你有效。
1)我将
headwordList
存储为一个集合,而不是一个列表,允许更快的访问,因为它是一个散列数据结构。2)您已将
sentenceList
定义为列表,然后尝试将其用作具有sentenceList[x] = y
的字典。我会为计数定义一个不同的结构。3)您构造
sentenceList
,这不需要完成。4)您从不标记
line
,这意味着您将整行存储在sentenceList中的换行符之前,并查看它是否在wordlist中有两件事可以提供一些小帮助:
1)使用this SO answer中的方法最有效地读取大文件。
2)更改代码
到
你要把每个句子转换成65万次。没必要那么做。
相关问题 更多 >
编程相关推荐