rendered paste bodydef getind(seq, i, default):
"""Convience function"""
try: return seq[i]
except LookupError: return default
fuzzycache = dict() #cached results of fuzzydistance()
def clearcache():
"""Clear the fuzzydistance() cache"""
fuzzycache.clear()
def fuzzydistance(a, b):
"""
Calculates the number of edit operations it takes to transform string a and string b.
The possible operations are each weighted with different values
delete - 3 points
insert - 3 points
swap - 2 points
substitute - 2 points
strip - 1 point
The weights are intended to detect abbreviations and typos as closely as possible.
The lower the return value, the more similst the strings are.
"""
try:
return fuzzycache[a,b]
except KeyError:
dist = _fuzzydist(a, b)
fuzzycache[a,b] = dist
return dist
def _fuzzydist(x, y, dist=0):
xchar = getind(x, 0, None)
ychar = getind(y, 0, None)
nextxchar = getind(x, 1, None)
nextychar = getind(y, 1, None)
if xchar == None:
return dist + len(y)
elif ychar == None:
return dist + (len(x) * 3)
else:
options = []
if xchar == ychar:
options.append((0, 1, 1))
else:
options.append((2, 1, 1))
if (xchar, nextxchar) == (nextychar, ychar):
options.append((2, 2, 2))
elif xchar == nextychar:
options.append((3, 0, 1))
elif ychar == nextxchar:
options.append((3, 1, 0))
return min(_fuzzydist(x[xi:], y[yi:], dist+d) for d,xi,yi in options)
def test(seq):
import profile
for a,b in seq:
profile.runctx("fuzzydistance(a,b)", globals(), locals())
print "fuzzydistance(%r, %r) == %r" % (a,b, fuzzydistance(a,b))
print "------------------------------"
#fuzzydistance(a,b)
if __name__ == "__main__":
test(
[("Goffredo", "Geoffrey"),
("Goffredo", "Gofredo"),
("Lea", "Leanna"),
("Brit", "Britanny"),
("Britanny", "Brit"),
("Kurt", "Krut"),
("Hippo", "Haiku"),
("bicker", "bcisjfeflge")]
)