我使用NLTK制作自己的押韵是Python。 CMU-dict有超过130,000个条目,格式如下:
[['griffon', ['G', 'R', 'IH1', 'F', 'AH0', 'N']],
['griffy', ['G', 'R', 'IH1', 'F', 'IY0']],
['grigas', ['G', 'R', 'AY1', 'G', 'AH0', 'Z']]]
这些是单词,pron(unciation)对。我操纵了它们(可能会为一个' T'切换一个' G)并检查它是否是一个单词。我这样做是通过使用这个函数:
all_word_prons = get_word_pron_pairs_in_cmu_dict()
def pron_is_a_word(pronunciation):
for word, pron in all_word_prons:
if pronunciation == pron:
return True
else:
return False
all_word_prons是一个Python Pickle文件,它是10mb并包含所有130k条目
如果我执行此查找1000次,则需要大约23秒,考虑到任务并不是完全错误,但必须有更好的算法。我已经看到人们推荐关于其他主题的二等分设置,但那些适用于简单的字符串查找。这或多或少地检查列表是否相等,而不是字符串。
我确实实现了一些包含这样数据的树状结构(使用上面的示例):
{'G': {'R': {'IH1': {'F': {'IY0': {0: 'griffy'}, 'AH0': {'N': {0: 'griffon'}}}}, 'AY1': {'G': {'AH0': {'Z': {0: 'grigas'}}}}}}}
由于某种原因,这需要比简单地迭代它更长的时间。也许我的实施是错误的。如果你有点好奇:
def build_fast_idict_tree():
from nltk.corpus import cmudict
entries = cmudict.entries()
idict = {}
for entry in entries:
word, pronunciation = entry
idict_level = idict
for syl in pronunciation:
if syl not in idict_level:
idict_level[syl] = {}
idict_level = idict_level[syl]
idict_level[0] = word
return idict
def get_fast_idict_tree():
filename = "fast_idict_tree.pickle"
if os.path.isfile(filename):
list = pickle.load(open(filename, "rb"))
else:
list = build_fast_idict_tree()
pickle.dump(list, open(filename, "wb"))
return list
def lookup_in_fast_idict_tree(syls):
idict = get_fast_idict_tree()
for syl in syls:
if syl not in idict:
return False
idict= idict[syl]
return idict[0] if 0 in idict else False
2015年在Python 3中进行此类查找(匹配列表)的最快方法是什么?
答案 0 :(得分:2)
如果我理解正确,您需要检查数据集中是否有pronunciation
。从您的第一个代码块开始,您似乎并不关心匹配来自word
的内容。
因此,我认为我们可以做到:
pron_set = {tuple(pron) for word, pron in all_word_prons}
# do something to get a list of pronunciations to check
for pronunciation in pronunciation_list:
if tuple(pronunciation) in pron_set:
print('pronunctiation')
我们从pron_set
构建tuple
因为list
s不可以播放(并且不能用作集合成员)。
设置查找应该比遍历列表快得多。我建议熟悉Python data structures;你永远不知道deque
什么时候可以节省你很多时间。
答案 1 :(得分:0)
您是否考虑过使用此处概述的Python列表推导?
https://docs.python.org/3/tutorial/datastructures.html
在某些情况下,列表推导可能比普通的for循环更快,但它仍然执行字节码级循环。如果你不确定我的意思,请查看以下帖子: Are list-comprehensions and functional functions faster than "for loops"?
可能值得一试,看看这会更快。