代码之家  ›  专栏  ›  技术社区  ›  Roee Adler

在python列表中查找“最近”字符串(按字母顺序)

  •  2
  • Roee Adler  · 技术社区  · 17 年前

    我有一个字符串的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循环迭代已排序的列表)

    进一步澄清:我对简单的字典字母比较感兴趣,而不是像列文施泰因或语音学这样的花哨的东西。

    谢谢

    4 回复  |  直到 17 年前
        1
  •  16
  •   Kenan Banks    17 年前

    这正是对分模块的作用所在。它将比只遍历大型列表快得多。

    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上写了这个,所以请检查是否有错别字。

        2
  •  2
  •   Bojan Resnik    17 年前

    您可以将问题重新表述为:

    给出了字符串的排序列表 l 和输入字符串 s ,在中查找索引 L 哪里 S 应插入,以便 L 插入后保持排序。

    元素 L 在 index-1 和 index+1 (如果它们存在的话)是你正在寻找的。为了找到索引,可以使用 binary search .

        3
  •  1
  •   Daniel Roseman    17 年前

    一个非常幼稚的实现,只适用于短列表:您可以非常容易地遍历列表并将您的选择与每个列表进行比较,然后在第一次选择“大于”被比较的项时中断。

    for i, item in enumerate(l):
        if lower(item) > lower(input):
            break
    
    print 'below: %s, above, %s' % (l[i-1], item)
    
        4
  •  0
  •   Michael H.    17 年前

    这些是相对较短的列表,内容是变化的还是相当静态的?

    如果您有大量的字符串,而且它们相对固定,那么您可能需要考虑将数据存储在trie结构中。一旦你建造了它,你就可以很快很容易地搜索并找到你最接近的邻居。