I wrote this function to compare two strings and find their similarity. It returns the percent of their letters in common in place. ie "hello" and "yellow" share the "ello" (8 of 11 characters) and thus are 72.72 % similar. I feel like there is a better way to write this but I've yet to come up with it.
def RunComparison(str1, str2, param):
comp = Compare(str1, str2, param)
return comp.percent
class Compare:
def __init__(self, str1, str2, param):
self.str1 = str1.lower()
self.str2 = str2.lower()
self.param = param
self.most = 0
self.percent = self.LIC()
def LIC(self): # Letters in common only
totlen = float( len(self.str1)+len(self.str2) ) # Will run LICIP if more
backup = self.str2 # than if greater than
if totlen > 0: # required match is found
for x in self.str1:
if x in backup:
backup = backup.replace(x, "", 1)
InComn = len(self.str2) - len(backup)
percent = (InComn/totlen)*200
if percent >= self.param:
percent = self.LICIP()
if percent >= self.param:
return percent
def LICIP(self):
SearchResult = [ self.FindAll(self.str2, char) for char in self.str1 ]
Sequence = self.ElicitSequentialMatches( SearchResult )
Total = float( len(Sequence) )
percent = Total*200.0 / ( len(self.str1)+len(self.str2) )
return round(percent, 2)
def ElicitSequentialMatches( self, indices ):
# finds a good place to start prevents
# starting on an empty search result.
indices = [ x for x in indices if x ]
if indices:
return max(self.WalkPaths(indices, [indices[0][0]]), key=len)
else:
return []
def WalkPaths(self, path, directions ):
while path:
if len(directions)+len(path) <= self.most:
directions = []
break
try:
last = directions[-1]
except:
last = -1
path = path[1:]
if path:
option = self.NextGreatest(last, path[0])
if option:
directions += [ option ]
# consider the no-option option. Leave
# everything unchanged and continue down the path.
if not self.IsNextBest(last, option, path):
for x in self.WalkPaths(path, directions[:-1]):
yield x
dir_len = len(directions)
if dir_len > self.most:
# possibly just setting
# the return value instead of
# adding these directions
# to the list of possibilities
self.most = dir_len
yield directions
def IsNextBest(self, prev, option, path):
if not option:
return True
if prev + 1 == option:
return True
while path:
for x in path[0]:
if x > prev:
if x <= option:
return False
return True
path = path[1:]
return True
def NextGreatest(self, x, List):
for y in List:
if y > x: return y
return []
def FindAll(self, string, subj):
return [n for n, x in enumerate(string) if x == subj]