我已经进行了很多谷歌搜索,但是没有找到任何东西,所以如果我只是在搜索错误的东西,我真的很抱歉。
我正在编写MIT编程导论第5次作业的Ghost实现。
作为其中的一部分,我需要确定一个字符字符串是否是任何有效单词的开头。我有一个有效单词列表("wordlist")。
更新:我可以使用一些每次都会遍历列表的东西,例如Peter的简单建议:
def word_exists(wordlist, word_fragment):
return any(w.startswith(word_fragment) for w in wordlist)
我之前有:
wordlist = [w for w in wordlist if w.startswith(word_fragment)]
(来自这里)将列表缩小为以该片段开头的有效单词列表,并且如果wordlist为空,则认为是损失。我采取这种方法的原因是,我(错误地,请参见下文)认为这样可以节省时间,因为随后的查找只需要在较小的列表中搜索。
我意识到,这是在检查原始单词列表(38,000个左右的单词)中的每个项目的开头。当wordlist有序时,这似乎很愚蠢,并且理解可以在遇到单词片段之后停止。我尝试了这个:
newlist = []
for w in wordlist:
if w[:len(word_fragment)] > word_fragment:
# Take advantage of the fact that the list is sorted
break
if w.startswith(word_fragment):
newlist.append(w)
return newlist
但是我认为这大约是因为列表理解作为编译代码运行的缘故,速度差不多?
然后我想,更有效的方法可能是在列表中使用某种形式的二分查找来查找匹配单词的块。这是正确的方法吗,还是我漏掉了什么非常明显的东西?
显然,在这种情况下并不是真正的大问题,但我刚开始学习编程,希望做好每一件事。
更新:
我已经用简单测试脚本测试了以下建议。虽然Peter的二分搜索/ bisect在单次运行中显然更好,但我对缩小列表是否会在一系列片段中获胜感兴趣。实际上,它没有:
The totals for all strings "p", "py", "pyt", "pyth", "pytho" are as follows:
In total, Peter's simple test took 0.175472736359
In total, Peter's bisect left test took 9.36985015869e-05
In total, the list comprehension took 0.0499348640442
In total, Neil G's bisect took 0.000373601913452
创建第二个列表等操作的开销显然比搜索更长的列表花费更多时间。事后看来,这可能是最好的方法,因为“减少列表”的方法增加了第一次运行的时间,这是最坏的情况。
感谢大家提供的出色建议,Peter做出了最佳答案,干得好!