我以为我会分享这个稍微有趣的技巧,虽然它比其他代码需要更多的代码并且不是真正的“pythonic”.这将比其他解决方案需要更多的代码,但如果我查看其他人需要的时间,则应该相当快.
我们正在进行一些预处理以加速计算.基本方法如下:我们为字母表中的每个字母指定一个素数.例如. A = 2,B = 3,依此类推.然后,我们为字母表中的每个单词计算一个哈希值,这只是单词中每个字符的主要表示形式的乘积.然后,我们将每个单词存储在由哈希索引的字典中.
现在,如果我们想要找出哪些单词等同于说教科书,我们只需要为单词计算相同的散列并在字典中查找.通常(比如在C中)我们不得不担心溢出,但是在python中它甚至更简单:列表中具有相同索引的每个单词都将包含完全相同的字符.
这里是稍微优化的代码,在我们的例子中我们只需要担心字符也出现在给定的单词中,这意味着我们可以使用比其他方式更小的素数表(显而易见的优化只是分配字符,在单词中出现一个值 – 它无论如何都足够快,所以我没有打扰,这样我们只能预处理一次并为几个单词执行它.素数算法经常有用,所以无论如何你应该有一个;)
from collections import defaultdict
from itertools import permutations
PRIMES = list(gen_primes(256)) # some arbitrary prime generator
def get_dict(path):
res = defaultdict(list)
with open(path, "r") as file:
for line in file.readlines():
word = line.strip().upper()
hash = compute_hash(word)
res[hash].append(word)
return res
def compute_hash(word):
hash = 1
for char in word:
try:
hash *= PRIMES[ord(char) - ord(' ')]
except IndexError:
# contains some character out of range - always 0 for our purposes
return 0
return hash
def get_result(path, given_word):
words = get_dict(path)
given_word = given_word.upper()
result = set()
powerset = lambda x: powerset(x[1:]) + [x[:1] + y for y in powerset(x[1:])] if x else [x]
for word in (word for word in powerset(given_word) if len(word) >= 4):
hash = compute_hash(word)
for equiv in words[hash]:
result.add(equiv)
return result
if __name__ == '__main__':
path = "dict.txt"
given_word = "textbook"
result = get_result(path, given_word)
print(result)
在我的ubuntu单词列表(98k字)上运行相当快,但不是我称之为pythonic,因为它基本上是c算法的一个端口.如果你想比较多个单词,这很有用..