за один раз, вы вызываете Отдельные слова (post.text) для каждого слова поиска в словах поиска.Вы должны вызывать Отдельные слова только один раз для каждого post
в posts
.
То есть вместо:
for search_word in search_words:
for post in posts:
# do heavy work
вы должны вместо этого иметь:
for post in posts:
# do the heavy works
for search_word in search_words:
...
Если, как я и подозревал, то разделенные слова выполняют много строковых манипуляций, не забывайте, что манипуляции со строками в python относительно дороги, так как строка неизменна.
Еще одно улучшение, которое вы можете сделать, это то, что вы не делаетенужно сравнить каждое слово в search_words с каждым словом в post_words.Если вы сохраняете массив search_words и post_words, отсортированный по длине слова, вы можете использовать технику скользящего окна.По сути, так как search_word будет соответствовать post_word только в том случае, если разница в их длине меньше 2, вам нужно только проверить среди окна разности двух длин, тем самым сократив количество проверяемых слов, например:
search_words = sorted(search_words, key=len)
g_post_words = collections.defaultdict(list) # this can probably use list of list
for post_word in post_words:
g_post_words[len(post_word)].append(post_word)
for search_word in search_words:
l = len(search_word)
# candidates = itertools.chain.from_iterable(g_post_words.get(m, []) for m in range(l - 2, l + 3))
candidates = itertools.chain(g_post_words.get(l - 2, []),
g_post_words.get(l - 1, []),
g_post_words.get(l , []),
g_post_words.get(l + 1, []),
g_post_words.get(l + 2, [])
)
for post_word in candidates:
score = calculate_score(search_word, post_word)
# ... and the rest ...
(этот код, вероятно, не будет работать как есть, он просто иллюстрирует идею)