A list of strings, some of them are actually of the same content (as outlined) but of minor difference.
I want to find out the similar strings. A possible way is by using similarity ratio from SequenceMatcher of (difflib).
from difflib import SequenceMatcher
import itertools
mylist = [
"I say,",
"It's in the reach of my arms",
"The span of my hips,",
"The stride of my step,",
"The curl of my lips.",
"I'm a woman",
"Phenomenally.",
"Phenomenal woman,",
"That's me.",
"I say.",
"It's the fire in my eyes,",
"And the flash of my teeth,",
"The swing in my waist,",
"And the joy in my feet.",
"I'm a woman.",
"Phenomenally!",
"Phenomenal women,",
"That's us.",
]
for a, b in itertools.combinations(mylist, 2):
score = SequenceMatcher(None, a, b).ratio()
if score >= 0.90:
print (a + " TO " + b + " : " + str(SequenceMatcher(None, a, b).ratio()))
Output:
I'm a woman TO I'm a woman. : 0.9565217391304348
Phenomenally. TO Phenomenally! : 0.9230769230769231
Phenomenal woman, TO Phenomenal women, : 0.9411764705882353
When the list became very long, it takes long time to generate the output, so I am thinking to sort the list, and only measure the similarity of each string/element's nearest 3 neighbors.
For example, for elements #1 in the sorted list, it only measure itself against #2,#3,#4. for elements #10 in the sorted list, it only measure itself against [#7,#8,#9], and [#11,#12,#13].
So I tried:
mylist.sort(reverse=False)
for num, content in enumerate(mylist):
for a in mylist[num+1:num+4]:
score = SequenceMatcher(None, a, content).ratio()
if score >= 0.90:
print (a + " TO " + content + " : " + score)
for num, content in enumerate(mylist):
if num >= 4:
for a in mylist[num-1:num-4]:
score = SequenceMatcher(None, a, content).ratio()
if score >= 0.90:
print (a + " TO " + content + " : " + str(score))
Much faster it works with long list. But I am wondering, is there a better way? Thank you.
