Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python中编辑距离_Python_Algorithm_Edit_Distance - Fatal编程技术网

在Python中编辑距离

在Python中编辑距离,python,algorithm,edit,distance,Python,Algorithm,Edit,Distance,我正在用Python编写拼写检查程序。我有一个有效单词的列表(字典),我需要从这个字典中输出一个与给定无效单词的编辑距离为2的单词列表 我知道我需要从生成一个列表开始,该列表与无效单词的编辑距离为1(然后对所有生成的单词再次运行该列表)。我有三种方法,插入(…)、删除(…)和更改(…),它们应该输出编辑距离为1的单词列表,其中插入输出比给定单词多一个字母的所有有效单词,删除输出少一个字母的所有有效单词,更改输出一个不同字母的所有有效单词 我已经检查了很多地方,但我似乎找不到描述这个过程的算法。我

我正在用Python编写拼写检查程序。我有一个有效单词的列表(字典),我需要从这个字典中输出一个与给定无效单词的编辑距离为2的单词列表

我知道我需要从生成一个列表开始,该列表与无效单词的编辑距离为1(然后对所有生成的单词再次运行该列表)。我有三种方法,插入(…)、删除(…)和更改(…),它们应该输出编辑距离为1的单词列表,其中插入输出比给定单词多一个字母的所有有效单词,删除输出少一个字母的所有有效单词,更改输出一个不同字母的所有有效单词


我已经检查了很多地方,但我似乎找不到描述这个过程的算法。我提出的所有想法都涉及多次循环浏览字典列表,这将非常耗时。如果有人能提供一些见解,我将不胜感激。

您描述的具体算法称为Levenshtein距离。一个快速的Google抛出了几个Python库和计算公式。

这是我的Levenshtein distance版本

#this calculates edit distance not levenstein edit distance
word1="rice"

word2="ice"

len_1=len(word1)

len_2=len(word2)

x =[[0]*(len_2+1) for _ in range(len_1+1)]#the matrix whose last element ->edit distance

for i in range(0,len_1+1): #initialization of base case values

    x[i][0]=i
for j in range(0,len_2+1):

    x[0][j]=j
for i in range (1,len_1+1):

    for j in range(1,len_2+1):

        if word1[i-1]==word2[j-1]:
            x[i][j] = x[i-1][j-1] 

        else :
            x[i][j]= min(x[i][j-1],x[i-1][j],x[i-1][j-1])+1

print x[i][j]
def edit_distance(s1, s2): m=len(s1)+1 n=len(s2)+1 tbl = {} for i in range(m): tbl[i,0]=i for j in range(n): tbl[0,j]=j for i in range(1, m): for j in range(1, n): cost = 0 if s1[i-1] == s2[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] print(edit_distance("Helloworld", "HalloWorld")) def编辑_距离(s1、s2): m=len(s1)+1 n=len(s2)+1 tbl={} 对于范围(m)中的i:tbl[i,0]=i 对于范围(n)中的j:tbl[0,j]=j 对于范围(1,m)内的i: 对于范围(1,n)内的j: 如果s1[i-1]==s2[j-1]或1,则成本=0 tbl[i,j]=最小值(tbl[i,j-1]+1,tbl[i-1,j]+1,tbl[i-1,j-1]+成本) 返回tbl[i,j] 打印(编辑距离(“Helloworld”、“HalloWorld”))
您正在查看的内容称为编辑距离,下面是一个。有很多方法可以定义两个单词之间的距离,您想要的一个称为Levenshtein距离,这里是python中的DP(动态编程)实现

def levenshteinDistance(s1, s2):
    if len(s1) > len(s2):
        s1, s2 = s2, s1

    distances = range(len(s1) + 1)
    for i2, c2 in enumerate(s2):
        distances_ = [i2+1]
        for i1, c1 in enumerate(s1):
            if c1 == c2:
                distances_.append(distances[i1])
            else:
                distances_.append(1 + min((distances[i1], distances[i1 + 1], distances_[-1])))
        distances = distances_
    return distances[-1]

和a.

使用BK-tree或TRIE代替Levenshtein距离算法,因为这些算法比编辑距离算法复杂度更低。仔细浏览这些主题将给出详细的描述


这将帮助您了解有关拼写检查的更多信息。

此任务需要最小编辑距离

以下是我的MED a.k.a Levenshtein Distance版本

def MED_character(str1,str2):
    cost=0
    len1=len(str1)
    len2=len(str2)

    #output the length of other string in case the length of any of the string is zero
    if len1==0:
        return len2
    if len2==0:
        return len1

    accumulator = [[0 for x in range(len2)] for y in range(len1)] #initializing a zero matrix

    # initializing the base cases
    for i in range(0,len1):
        accumulator[i][0] = i;
    for i in range(0,len2):
        accumulator[0][i] = i;

    # we take the accumulator and iterate through it row by row. 
    for i in range(1,len1):
        char1=str1[i]
        for j in range(1,len2):
            char2=str2[j]
            cost1=0
            if char1!=char2:
                cost1=2 #cost for substitution
            accumulator[i][j]=min(accumulator[i-1][j]+1, accumulator[i][j-1]+1, accumulator[i-1][j-1] + cost1 )

    cost=accumulator[len1-1][len2-1]
    return cost
标准库中有各种用于序列匹配的实用程序,包括可以使用的
get\u close\u matches
方法。它使用了一种改编自Ratcliff和Obershelp的算法

来自文档

从difflib导入获取\u关闭\u匹配
#产量[‘苹果’、‘猿’]
接近匹配('appel',['ape','apple','peach','puppy'])
使用from Python内置的
difflib
是另一种方法,但是(正如注释中正确指出的那样),结果与编辑距离的定义并不完全匹配。好处:它支持忽略“垃圾”部分(例如空格或标点符号)


与上述Santoshi的解决方案类似,但我做了三个更改:

  • 一行初始化而不是五行初始化
  • 无需单独定义成本(只需使用int(布尔值)0或1)
  • 而不是双环使用产品(最后一个只是化妆品,双环似乎不可避免)

  • 您可能想看看Peter Norvig的拼写检查器()并对其进行修改以满足您的需要。NLTK Python包有一个用于计算这个的函数。您看到了吗?DP代表动态编程。@Salvador Dali不应该相邻的换位返回1的距离吗?上述函数提供了
    levenshteinstance(“abc”、“bac”)
    -->2@alancalvitti唯一的操作是插入、删除和替换。因此,在您的示例中,您需要删除
    a
    ,然后在
    b
    c
    之间重新插入它。两个操作。您好:),您是否碰巧有一个版本(或另一个算法)可以指定levenshtein距离的上限?(您也可以查看我的帖子了解更多详细信息:)您的代码不正确。逻辑不健全,
    返回tbl[i,j]
    应该是
    返回tbl[n,m]
    。对
    '123'
    '12345'
    运行此命令将生成长度为1的
    所需编辑,而编辑距离为2。
    
    from difflib import SequenceMatcher
    
    a = 'kitten'
    b = 'sitting'
    
    required_edits = [
        code
        for code in (
            SequenceMatcher(a=a, b=b, autojunk=False)
            .get_opcodes()
        )
        if code[0] != 'equal'
    ]
    required_edits
    # [
    #    # (tag, i1, i2, j1, j2)
    #    ('replace', 0, 1, 0, 1), # replace a[0:1]="k" with b[0:1]="s"
    #    ('replace', 4, 5, 4, 5), # replace a[4:5]="e" with b[4:5]="i"
    #    ('insert', 6, 6, 6, 7),  # insert b[6:7]="g" after a[6:6]="n"
    # ]
    
    
    # the edit distance:
    len(required_edits)  # == 3
    
    from itertools import product
    
    def edit_distance(s1,s2):      
       d={ **{(i,0):i for i in range(len(s1)+1)},**{(0,j):j for i in range(len(s2)+1)}}
       for i, j in product(range(1,len(s1)+1), range(1,len(s2)+1)): 
           d[i,j]=min(int(s[i-1]!=s[j-1]) + d[i-1,j-1], d[i-1,j]+1, d[i,j-1]+1)
       return d[i,j]