我正在用python编写一个搜索引擎,搜索一系列菜谱,它应该以一定的速度运行,每次搜索最多0.1秒。我一直在努力用代码达到这个速度。我平均得到0.4分。我想知道你是否知道如何使这段代码更快。我尝试了很多东西,但我知道循环是一个使它慢了很多。如果我能用python来改进它,而不是添加那么多模块的话。你知道吗
我已经在代码0.005 avg的其他部分做得更快了。但是在这个部分,有大量的食谱,它变得相当慢。你知道吗
def countTokens(token):
token = str(token).lower()
#make digits an punctuations white spaces
tokens = token.translate(token.maketrans(digits + punctuation,\
" "*len(digits + punctuation)))
return tokens.split(" ")
def normalOrder(recipes, queries):
for r in recipes:
k = r.keys()
parts, scores = [[],[],[],[]], 0
parts[0] = countTokens(r["title"])
parts[1] = countTokens(r["categories"]) if "categories" in k else []
parts[2] = countTokens(r["ingredients"]) if "ingredients" in k else []
parts[3] = countTokens(r["directions"]) if "directions" in k else []
for q in queries:
scores += 8 * parts[0].count(q) + 4 * parts[1].count(q) + 2 * parts[2].count(q) + 1 * parts[3].count(q)
r["score"] = scores + r["rating"] if "rating" in k else 0
return recipes
在一点上下文中,我需要对上面四个描述符中的查询的出现次数求和,只有当有它的时候,这就是为什么我有if的原因
首先可以使用
get
而不是if条件。你知道吗我注意到了几点:
countTokens
时,都会再次生成相同的翻译表(即maketrans
调用)。我猜这不会被优化掉,所以你可能会失去那里的性能。你知道吗tokens.split(" ")
创建字符串中所有单词的列表,这相当昂贵,例如当字符串为100000个单词时。你不需要这个。你知道吗如果你应用了它,你就不再需要
countTokens
函数了,再进行一点重构,结果就是:这对你有用吗?够快吗?你知道吗
编辑:在原始代码中,您将对
recipe["title"]
的访问和其他字符串包装在另一个str()
调用中。我猜它们已经是绳子了?如果不是,你需要在这里加上。你知道吗你在评论中说标点符号是个问题。正如我在评论中所说的,我认为您不必担心这一点,因为
count
调用将只关心标点字符如果查询词和配方文本都包含标点字符,那么count调用将只统计周围标点与所查询内容相匹配的出现次数。看看这些例子:如果你想让它有不同的表现,你可以像你在原始问题中所做的那样:创建一个翻译表并应用它。 请记住,将此翻译应用于配方文本(正如您在问题中所做的那样)没有多大意义,因为从那时起,任何包含标点符号的查询词都不匹配。只需忽略所有包含标点符号的查询词,就可以轻松地完成这项工作。 您可能希望对查询词进行翻译,这样,如果有人输入“potato”,您就可以找到所有出现的“potato”。这看起来像这样:
Edit3:在评论中,你说你想搜索[“蜂蜜”,“柠檬”]来匹配“蜂蜜柠檬”,但是你不想“黄油”来匹配“黄油手指”。为此,您的初始方法可能是最好的解决方案,但请记住,搜索单数形式“potato”将不再匹配复数形式(“potato”)或任何其他派生形式。你知道吗
如果使用相同的recipes更频繁地调用此函数,则可以通过在recipes中存储
.lower().translate().split()
的结果来获得更高的性能,这样就不需要在每次调用中重新创建该列表。你知道吗根据您的输入数据(平均有多少个查询?),只需遍历
split()
结果一次,然后将每个单词的计数相加,也可能是有意义的。这将使查找单个单词的速度大大加快,也可以在函数调用之间保留,但构建成本更高:Edit4:我已经用一个计数器替换了defaultdict,因为我不知道类的存在。你知道吗
相关问题 更多 >
编程相关推荐