用Python实现文本文件中两个单词的Levinstein距离
我有一个30行的文本文件,每行有两个相似的单词。我需要计算每行两个单词之间的距离。我还需要在计算距离时使用一个函数。一般来说,我对Python和算法是相当陌生的,所以这对我来说是相当困难的。我打开了文件并正在读取,但我不知道如何将这两个字分别赋给变量“a”和“b”来计算距离 以下是我当前的脚本,目前仅打印文档:用Python实现文本文件中两个单词的Levinstein距离,python,algorithm,levenshtein-distance,Python,Algorithm,Levenshtein Distance,我有一个30行的文本文件,每行有两个相似的单词。我需要计算每行两个单词之间的距离。我还需要在计算距离时使用一个函数。一般来说,我对Python和算法是相当陌生的,所以这对我来说是相当困难的。我打开了文件并正在读取,但我不知道如何将这两个字分别赋给变量“a”和“b”来计算距离 以下是我当前的脚本,目前仅打印文档: txt_file = open('wordfile.txt', 'r') def memoize(f): cache = {} def wrapper(*args, *
txt_file = open('wordfile.txt', 'r')
def memoize(f):
cache = {}
def wrapper(*args, **kwargs):
try:
return cache[args]
except KeyError:
result = f(*args, **kwargs)
cache[args] = result
return result
return wrapper
@memoize
def lev(a,b):
if len(a) > len(b):
a,b = b,a
b,a = a,b
current = range(a+1)
for i in range(1,b+1):
previous, current = current, [i]+[0]*n
for j in range(1,a+1):
add, delete = previous[j]+1, current[j-1]+1
change = previous[j-1]
if a[j-1] != b[i-1]:
change = change + 1
current[j] = min(add, delete, change)
return current[b]
if __name__=="__main__":
with txt_file as f:
for line in f:
print line
以下是文本文件中的几句话,以便大家了解:
原型,原型
专有财产
识别
排除,排除
龙卷风
发生,发生
真空度,附近
这是脚本的更新版本,仍然不起作用,但更好一些:
class memoize:
def __init__(self, function):
self.function = function
self.memoized = {}
def __call__(self, *args):
try:
return self.memoized[args]
except KeyError:
self.memoized[args] = self.function(*args)
return self.memoized[args]
@memoize
def lev(a,b):
n, m = len(a), len(b)
if n > m:
a, b = b, a
n, m = m, n
current = range(n + 1)
for i in range(1, m + 1):
previous, current = current, [i] + [0] * n
for j in range(1, n + 1):
add, delete = previous[j] + 1, current[j - 1] + 1
change = previous[j - 1]
if a[j - 1] != b[i - 1]:
change = change + 1
current[j] = min(add, delete, change)
return current[n]
if __name__=="__main__":
for pair in open("wordfile.txt", "r"):
a,b = pair.split()
lev(a, b)
假设问题是将单词传递给
lev
。假设你的wordfile是这样的-
bat, man
cat, goat
foo, bar
那么你可以这样做-
if __name__ == '__main__':
for pair in open("wordfile", "r"):
# first, remove all spaces, then break around the comma
a,b = pair.replace(' ', '').split(',')
# pass these words to lev
lev(a, b)
在阿披舍克的回答和评论的帮助下,我找到了这个问题的答案。以下是最终的功能脚本,以防其他人需要它:
def memoize(f):
cache = {}
def wrapper(*args, **kwargs):
try:
return cache[args]
except KeyError:
result = f(*args, **kwargs)
cache[args] = result
return result
return wrapper
@memoize
def lev(a,b):
n, m = len(a), len(b)
if n > m:
a, b = b, a
n, m = m, n
current = range(n + 1)
for i in range(1, m + 1):
previous, current = current, [i] + [0] * n
for j in range(1, n + 1):
add, delete = previous[j] + 1, current[j - 1] + 1
change = previous[j - 1]
if a[j - 1] != b[i - 1]:
change = change + 1
current[j] = min(add, delete, change)
return current[n]
if __name__=="__main__":
lev = Counter(lev)
word_file = open('wordfile.txt', 'r')
for line in word_file:
a,b = line.split()
print a,b, lev(a, b)
将定义(memoize、lev等)和实际任务(读取文件、循环)分开是一个很好的做法。也就是说,将所有定义放在
if
语句前面,脚本的所有主要工作都放在if
语句下面。因此,在检查\uuu name\uuu
之后打开调用会很好。我觉得current=range(a+1)
是lev
实现的一部分,请尝试正确缩进它。现在,为了更清楚,您可以展示一下wordfile.txt
中的几行吗?在这个场景中,单词是由什么组成的?我假设任何只有字母的东西,但这就是你的假设吗?是的,任何只有字母的东西。这些单词非常简单,非常相似,每个单词中都没有几个字母。为了清楚起见,我在问题中添加了几个单词。您的lev()函数似乎没有返回任何内容?这是故意的吗?嗯,你更新的代码确实会返回值,只需在主循环中打印lev(a,b)
,然后查看:)好的,这允许我将单词分配给a&b变量,但现在我遇到了这样一个错误:“无法连接'str'和'int'对象”,其中我没有使用任何整数?编辑:错误来自行current=range(a+1)
您正在添加a+1,但a是一个字符串“range(a+1)”。如果您希望生成的范围比变量a
(这是一个字符串)的长度大1,您可以执行range(len(a)+1)
hmm,它仍然不起作用。每次我将范围更改为您上面所说的范围时,我都会在脚本的整个过程中出错。。。以下是两个主要错误:“无法连接'str'和'int'对象”&“列表索引必须是整数,而不是str”您可以将最新脚本粘贴到其他位置,并在此处传递链接吗?