【问题标题】:How can I sort a string list based on edit distance efficiently?如何有效地根据编辑距离对字符串列表进行排序?
【发布时间】:2020-12-10 20:03:48
【问题描述】:

我正在尝试使用 levenshtein 距离按编辑距离对列表进行排序。

def suggest(dic, word, distance, maxSugestions=5):
   list = []
   for i in range(1, 200):
       for word1 in sorted(dic):
           if distance(word1, word) == i:
               list.append(word1)
               if len(list) == maxSugestions:
                   return list

这是我当前的函数,它接收一个字符串列表(这个列表有大约 43000 个字符串),一个我想比较的单词,一个返回两个字符串之间的编辑距离的函数和一个整数 maxSugestions 列表应该有。

这是当前距离函数:

def levDistance(str1, str2):
   matrix = [[0 for x in range(len(str2) + 1)] for x in range(len(str1) + 1)]

   for i in range(len(str1) + 1):
       for j in range(len(str2) + 1):
           if i == 0:
               matrix[i][j] = j
           elif j == 0:
               matrix[i][j] = i
           elif str1[i-1] == str2[j-1]:
               matrix[i][j] = matrix[i-1][j-1]
           else:
               matrix[i][j] = 1 + min(matrix[i][j-1], matrix[i-1][j], matrix[i-1][j-1])    

   return matrix[len(str1)][len(str2)]

当前的建议()函数有效,但是我需要对其进行优化,因为它花费的时间太长而且我不知道该怎么做。任何帮助都将不胜感激。谢谢

【问题讨论】:

  • 您是否尝试过使用sorted 并指定key
  • 如果多次计算相同的距离,最好先创建所有距离的字典{(word1,word2):distance, ... }
  • 在当前代码中,您在 for i in range(1, 200) 内运行 sorted(dic),因此您重复相同的排序 200 次 - 您只能在 for-loop 之前对其排序一次
  • 当你有字典 {(word1,word2):distance, ... } 然后你可以使用函数 sorted(..., key=...)key 它使用`距离来排序它

标签: python


【解决方案1】:

您在每次迭代中计算相同的距离,这是一个很大的禁忌。而是尝试仅计算一次,然后获得 maxSuggestion 定义的建议数量:

def suggest(dic, word, distance, maxSugestions=5):
   return [i[1] for i in sorted([(distance(word1, word), word1) for word1 in dic])[:maxSuggestion]]

然后是您的实施!如果您仍然希望它更快,最好使用editdistance 库。 (或任何其他基于 C 的实现,如果重要的话)而不是基于 python 的实现。 For me it went 20x faster than python implementation.来自原答案:

我使用基于 c 的实现来计算 levenshtein 距离 利用:editdistance 库。在研究中我发现 许多此类任务都有基于 C 的实现,例如 矩阵乘法和搜索算法等很容易 可用的。此外,您始终可以用 C 编写模块并使用 它在python中。 editdistance.eval('banana', 'bahama') 只拍了1.71 µs ± 289 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each) 与我定义的函数 levenshteinDistance('banana', 'bahama') 相比,它采用了 34.4 µs ± 4.2 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each),这是 20 倍的加速。

附:我不是该软件包的作者,并且使用名义上的谷歌搜索“基于 C 的 levenshtein 距离实现”找到了该软件包

【讨论】:

    【解决方案2】:

    我试过这个技巧,希望对你有用

    def edit_distance(word, string_to_take_distance_with = "someString"):
        '''
        Description:
            give you the edit distance between 2 words
            word                            : String 1 (dynamic) 
            string_to_take_distance_with    : String 2 (static)
            
        '''
        
        
        length_of_string  = len(word)+1
        length_of_string2 = len(string_to_take_distance_with)+1
    
        tbl = {}
        for i in range(length_of_string): tbl[i,0]=i
        for j in range(length_of_string2): tbl[0,j]=j
        for i in range(1, length_of_string):
            for j in range(1, length_of_string2):
                cost = 0 if word[i-1] == string_to_take_distance_with[j-1] else 1
                tbl[i,j] = min(tbl[i, j-1]+1, tbl[i-1, j]+1, tbl[i-1, j-1]+cost)
    
        return tbl[i,j]
    
    
    
    
    sorted(["hello","helo","aen"], key=edit_distance)
    

    【讨论】:

      猜你喜欢
      • 2021-05-14
      • 2012-03-26
      • 2021-12-20
      • 2018-02-23
      • 1970-01-01
      • 2021-11-18
      • 2014-08-30
      • 1970-01-01
      • 2012-05-18
      相关资源
      最近更新 更多