匹配所有相关字符串

时间:2015-01-29 12:42:23

标签: python regex

我有一个文本文件,其中包含一些文本文件,如下所示。

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']

2 个答案:

答案 0 :(得分:2)

我不认为正则表达式是正确的。

但是,您可以使用Union FindMinimum Edit Distance的组合来执行此操作。

对于每个单词组合,确定min_edit_dist,如果距离小于某个阈值,则union这些单词组合在一起。为该阈值选择正确的值可能取决于单词的选择。对于您的话,34似乎运作良好。

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()

输出,用于unionfindmin_edit_dist的实现:

[set(['laptop bag']), 
 set(['gruop', 'grop', 'group']), 
 set(['buk', 'book', 'bok']), 
 set(['laftop', 'laptop', 'leptop']), 
 set(['pencil', 'pancil', 'pensil'])]

有关unionfind功能,请参阅this answermin_edit_dist函数的实现留给读者练习。

这种方法可能存在的问题是,如果它们之间存在足够密切的差异,它可能最终会合并所有组。


关于使用difflib.find_close_matches的自己的方法:

您可以使用cutoff参数微调匹配应该“关闭”的方式。但是,我没有找到适合所有示例的值,更不用说可能在那里的所有其他值。 0.8适用于laptop,但对book过于严格。另请注意,使用此方法,您需要知道哪些是“根词”,这可能是实践中的一个问题。

另一方面,我的方法不需要先知道哪些词是该组的“领导者”,而是自己找到它们。对于类似的技术,您可能还想查看cluster analysis algorithms

答案 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的解决方案都适用于一个类,那么你可以使用一个天真的方法,否则你需要更聪明的东西。