我有一个文本文件,其中包含一些文本文件,如下所示。
file.txt的
leptop
pencil
group
leptop
book
gruop
buk
grop
laftop
pensil
laptop
pancil
laptop bag
bok
从该文件我需要找出相关的查询并存储到如下列表中。
[leptop,leptop,laftop,laptop]
[pencil,pensil,pancil]
[group,gruop,grop]
[book,buk,bok]
[laptop bag]
我找到了类似下面的东西。它工作得很好。但我想对此进行一些修改。
import keyword
from difflib import get_close_matches
lis = ["leptop","pencil","group","leptop","book","gruop","bowk","grop","laftop","pensil","laptop","pancil","laptop bag","bok"]
print get_close_matches("laptop",lis, n = len(lis))
print get_close_matches("pencil", lis, n = len(lis))
print get_close_matches("group", lis, n = len(lis))
print get_close_matches("book", lis, n = len(lis))
输出: -
['laptop', 'leptop', 'leptop', 'laftop', 'laptop bag'] # i don't want "laptop bag" as output over here.
['pencil', 'pensil', 'pancil']
['group', 'grop', 'gruop']
['book', 'bok', 'bowk']
答案 0 :(得分:2)
我不认为正则表达式是正确的。
但是,您可以使用Union Find和Minimum Edit Distance的组合来执行此操作。
对于每个单词组合,确定min_edit_dist
,如果距离小于某个阈值,则union
这些单词组合在一起。为该阈值选择正确的值可能取决于单词的选择。对于您的话,3
或4
似乎运作良好。
import collections, itertools
# initialize 'leaders' dictionary, used in union and find
leaders = {word: None for word in words}
# union similar words together
for u, v in itertools.combinations(words, 2):
if find(u) != find(v) and min_edit_dist(u, v) < 3:
union(u, v)
# determine groups of similar words by their leaders
groups = collections.defaultdict(set)
for x in leaders:
groups[find(x)].add(x)
print groups.values()
输出,用于union
,find
和min_edit_dist
的实现:
[set(['laptop bag']),
set(['gruop', 'grop', 'group']),
set(['buk', 'book', 'bok']),
set(['laftop', 'laptop', 'leptop']),
set(['pencil', 'pancil', 'pensil'])]
有关union
和find
功能,请参阅this answer。 min_edit_dist
函数的实现留给读者练习。
这种方法可能存在的问题是,如果它们之间存在足够密切的差异,它可能最终会合并所有组。
关于使用difflib.find_close_matches
的自己的方法:
您可以使用cutoff
参数微调匹配应该“关闭”的方式。但是,我没有找到适合所有示例的值,更不用说可能在那里的所有其他值。 0.8
适用于laptop
,但对book
过于严格。另请注意,使用此方法,您需要知道哪些是“根词”,这可能是实践中的一个问题。
答案 1 :(得分:1)
首先,您需要定义&#34;相关的&#34;装置
从你的例子中可以看出,如果一个&#34;字符变化很小,那么单词a和b是相关的,以获得b&#34; ...请参阅有关Levenshtein距离的其他评论,这正是您想要使用的:Levenshtein或Minimum-Edit-Distance需要两个单词a和b,并给出一个数字dist(a,b),如果a = b,则为0你获得b所需的变化越多,就越高。
使用这个&#34;工具&#34;你可以开始建立一个解决你的问题的算法,例如通过定义一个距离,意味着&#34;相关的&#34;并逐行取每个字,并检查它与下面任何一个字的距离是否小。
但是你真的需要考虑你想要达到的目标。使用天真的方法可以将输入中的所有单词放入一个&#34;类&#34;如果它们都是传递相关的。
示例:foo / fool是相关的,fool / pool是相关的,pool / bool是相关的。 现在foo可能不是&#34;相关&#34;根据你最初的想法来加油,但它是通过一系列相关词汇来联系的。
如果你对foo / fool / pool / bool的解决方案都适用于一个类,那么你可以使用一个天真的方法,否则你需要更聪明的东西。