我有一个Python字符串列表,例如初始化如下:
l = ['aardvark', 'cat', 'dog', 'fish', 'tiger', 'zebra']
我想测试一个输入字符串对这个列表,并找到“它下面最近的字符串”和“它上面最近的字符串”,按字母顺序和不区分大小写(即没有语音,只有a<b
等)。如果输入存在于列表中,则“下方”和“上方”都应返回输入。
几个例子:
Input | Below | Above
-------------------------------
bat | aardvark | cat
aaa | None | aardvark
ferret | dog | fish
dog | dog | dog
在Python中实现这一目标的最佳方法是什么? (目前我正在使用for循环遍历排序列表)
进一步澄清:我对简单的字典字母比较感兴趣,而不是像Levenshtein或语音学那样的任何想法。
由于
答案 0 :(得分:16)
这正是bisect模块的用途。它比仅仅遍历大型列表要快得多。
import bisect
def closest(haystack, needle):
if len(haystack) == 0: return None, None
index = bisect.bisect_left(haystack, needle)
if index == 0:
return None, haystack[0]
if index == len(haystack):
return haystack[index], None
if haystack[index] == needle:
return haystack[index], haystack[index]
return haystack[index-1], haystack[index]
上面的代码假设您已将输入和列表清理为全部大写或小写。另外,我在iPhone上写了这个,所以请检查拼写错误。
答案 1 :(得分:2)
您可以将问题重新解释为:
给定字符串l
和输入字符串s
的排序列表,找到l
中应插入s
的索引,以便l
保持不变插入后排序。
l
index-1
和index+1
(如果存在)的元素是您正在寻找的元素。要查找索引,您可以使用binary search。
答案 2 :(得分:1)
一个非常天真的实现,仅适用于短列表:您可以非常轻松地遍历列表并将您的选择与每个列表进行比较,然后在您选择的第一次“比正在比较的项目更大”时中断。
for i, item in enumerate(l):
if lower(item) > lower(input):
break
print 'below: %s, above, %s' % (l[i-1], item)
答案 3 :(得分:0)
这些相对较短的列表,内容是否发生变化或是否相当静态?
如果您有大量字符串,而且它们相对固定,您可能需要考虑将数据存储在Trie结构中。一旦你建立它,那么它是快速的&amp;您可以按照自己喜欢的方式轻松搜索并找到最近的邻居。