【发布时间】:2015-05-20 02:38:25
【问题描述】:
我正在使用 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']]]
这些是单词、发音(发音)对。我操纵了prons(也许将'G'换成'T')并检查这是否是一个词。我通过使用这个函数来做到这一点:
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
TL:DR
2015 年在 Python 3 中进行这种查找(匹配列表)的最快方法是什么?
【问题讨论】:
-
是否有任何特殊原因您没有将发音转换为
tuple(以便您可以散列它们)然后将它们扔进set?或者dict,如果您仍想将它们映射到原始单词。 -
也就是说,这只是duplicate of this吗?
-
没有。这是完全正确的。我想我不认为字典会快得多。我错了。它们的速度要快得多(1000 次查找不到一秒......)。将发音转换为元组,然后将它们作为键并使用 .get(pronunciation, False) 进行某种错误报告。奇迹般有效。谢谢。