[英]regular expression: search multiple words with multiple parts
我正在尝试实现搜索一组包含多个部分的多个单词。 例如,我们有这些医学术语。
R Deep Transverse Metatarsal Ligament 4 GEODE
R Distal JointCapsule 1 GEODE
R Dorsal Calcaneocuboid Ligament GEODE
R Dorsal Carpometacarpal Ligament 2 GEODE
R Dorsal Cuboideavicular Ligament GEODE
R Dorsal Tarsometatarsal Ligament 5 GEODE
R Elbow Capsule GEODE
R F Distal JointCapsule 1 GEODE
R Fibular Collateral Bursa GEODE
R Fibular Collateral Ligament GEODE
R Fibular Ligament GEODE
用户可以输入如下搜索词:
例如,“ R De Me Li”,则应找到“ R Deep Trans横向s骨韧带4 GEODE”
例如,“ Fi Colla” ==>“ R腓侧副韧带GEODE”,“ R腓侧副韧带GEODE”
例如,“弓形ODE” ==>“ R肘形胶囊GEODE”
也就是说,即使用户输入单词的某些部分,它也应该找到答案。 如果有多个答案,则应全部显示。 非常感谢您的帮助。
添加)哦..我忘记了一些东西。
例如,“ ral lar” ==>不应显示“ R腓侧副韧带GEODE”或“ R腓侧副韧带GEODE”,因为应考虑查询词的顺序。
另外,查询词之间的空格表示每行(数据库)的不同词。
查询词的顺序应与每行(数据库)的词相同,但是查询词可以比数据库词短。
例如,“ R De Me 4” ==>“ R横向横Meta韧带4 GEODE”在这里我们可以看到'Metatarsal'和'Ligament'包含'me',但是与'Metatarsal'的第一个匹配很好,并且4将被搜索。
此外,查询词的不同组合可以返回相同的结果。
例如。,
'汽车'==>'R腕掌韧带2 GEODE'
'Do Car'==>'R背腕掌韧带2 GEODE'
'R Do Carp'==>'R背腕掌韧带2 GEODE'
注意:不区分大小写。
您可以在标准发行版中使用difflib进行此操作:
import difflib
s="""R Deep Transverse Metatarsal Ligament 4 GEODE
R Distal JointCapsule 1 GEODE
R Dorsal Calcaneocuboid Ligament GEODE
R Dorsal Carpometacarpal Ligament 2 GEODE
R Dorsal Cuboideavicular Ligament GEODE
R Dorsal Tarsometatarsal Ligament 5 GEODE
R Elbow Capsule GEODE
R F Distal JointCapsule 1 GEODE
R Fibular Collateral Bursa GEODE
R Fibular Collateral Ligament GEODE
R Fibular Ligament GEODE""".split('\n')
qs="""R De Me Li
Fi Colla
bow ODE""".split('\n')
for q in qs:
print "results for '{}':".format(q)
matches=difflib.get_close_matches(q,s,3,0.3)
for i,e in enumerate(matches,1):
print "\t{}. {}".format(i,e)
印刷品:
results for 'R De Me Li':
1. R Deep Transverse Metatarsal Ligament 4 GEODE
2. R Dorsal Calcaneocuboid Ligament GEODE
3. R Dorsal Cuboideavicular Ligament GEODE
results for 'Fi Colla':
1. R Fibular Collateral Bursa GEODE
2. R Fibular Collateral Ligament GEODE
results for 'bow ODE':
1. R Elbow Capsule GEODE
结合cblab有关将regex与difflib结合的答案 ,可以得到以下信息:
s="""R Deep Transverse Metatarsal Ligament 4 GEODE
R Distal JointCapsule 1 GEODE
R Dorsal Calcaneocuboid Ligament GEODE
R Dorsal Carpometacarpal Ligament 2 GEODE
R Dorsal Cuboideavicular Ligament GEODE
R Dorsal Tarsometatarsal Ligament 5 GEODE
R Elbow Capsule GEODE
R F Distal JointCapsule 1 GEODE
R Fibular Collateral Bursa GEODE
R Fibular Collateral Ligament GEODE
R Fibular Ligament GEODE""".split('\n')
s=set(s)
qs="""R De Me Li
Fi Colla
bow ODE
Car
Do Car
ral lar
R De Me 4
R Do Carp""".split('\n')
for q in sorted(qs):
print "results for '{}':".format(q)
pattern = r'.*' + re.sub(r'\W', '.*', q.strip()) + '.*'
matches=[item for item in s if re.match(pattern, item, re.I)]
for e in difflib.get_close_matches(q,s,3,0.33):
if e not in matches:
matches.append(e)
for i,e in enumerate(matches,1):
print "\t{}. {}".format(i,e)
else:
if len(matches)==0:
print "\tNo matches"
印刷品:
results for 'Car':
1. R Dorsal Carpometacarpal Ligament 2 GEODE
results for 'Do Car':
1. R Dorsal Carpometacarpal Ligament 2 GEODE
results for 'Fi Colla':
1. R Fibular Collateral Bursa GEODE
2. R Fibular Collateral Ligament GEODE
results for 'R De Me 4':
1. R Deep Transverse Metatarsal Ligament 4 GEODE
results for 'R De Me Li':
1. R Deep Transverse Metatarsal Ligament 4 GEODE
2. R Dorsal Calcaneocuboid Ligament GEODE
results for 'R Do Carp':
1. R Dorsal Carpometacarpal Ligament 2 GEODE
2. R Elbow Capsule GEODE
3. R Distal JointCapsule 1 GEODE
results for 'bow ODE':
1. R Elbow Capsule GEODE
results for 'ral lar':
No matches
一个简单的pythonic解决方案,它按照回答进行工作,并且不区分大小写 :
import re
def search(request, base):
pattern = r'.*' + re.sub(r'\W', '.*', request.strip()) + '.*'
return [item for item in base if re.match(pattern, item, re.I)]
基本上,我们创建一个简单的正则表达式,以原始顺序匹配包含请求的所有子字符串(所有内容均由非单词字符分隔)的所有字符串,以及之前,之中和之后的任何内容。
例如,请求'R De Me Li'
成为模式r'.*R.*De.*Me.Li.*'
然后,我们返回 所有匹配结果 的列表 。 由于re.match()
的标记re.I
,所以它不区分大小写。
然后,它可以按预期工作,您可以尝试使用基础:
>>> base = ['R Deep Transverse Metatarsal Ligament 4 GEODE',
'R Distal JointCapsule 1 GEODE',
'R Dorsal Calcaneocuboid Ligament GEODE',
'R Dorsal Carpometacarpal Ligament 2 GEODE',
'R Dorsal Cuboideavicular Ligament GEODE',
'R Dorsal Tarsometatarsal Ligament 5 GEODE',
'R Elbow Capsule GEODE',
'R F Distal JointCapsule 1 GEODE',
'R Fibular Collateral Bursa GEODE',
'R Fibular Collateral Ligament GEODE',
'R Fibular Ligament GEODE']
一些示例请求:
>>> search('R De Me Li', base)
['R Deep Transverse Metatarsal Ligament 4 GEODE']
>>> search('Fi Colla', base)
['R Fibular Collateral Bursa GEODE', 'R Fibular Collateral Ligament GEODE']
>>> search('bow ODE', base)
['R Elbow Capsule GEODE']
>>> search('Car', base)
['R Dorsal Carpometacarpal Ligament 2 GEODE']
>>> search('F', base)
['R F Distal JointCapsule 1 GEODE', 'R Fibular Collateral Bursa GEODE', 'R Fibular Collateral Ligament GEODE', 'R Fibular Ligament GEODE']
>>> search('F Ca', base)
['R F Distal JointCapsule 1 GEODE']
>>> search('F Co', base)
['R Fibular Collateral Bursa GEODE', 'R Fibular Collateral Ligament GEODE']
注意:仅当请求中和项目中的顺序相同时,它才会匹配(例如, 'ode bow'
作为请求将不匹配['R Elbow Capsule GEODE']
,而'bow ode'
将匹配)。
注意: 至少在起初 ,我认为模糊搜索不会有太大帮助,因为它基于Levenshtein(编辑距离)之类的距离,例如“ Fi”和“ Fibular”之间的距离会很大( 5的单词中的7的距离... 35%时,我不知道这是个好主意...如果您可以确定请求中只包含完整的单词,可能会有一点点误会,可以使用它
并不是真正的“正则表达式”问题; 您应该查看字符串的模糊比较,即Levenshtein距离或diff。
参见https://stackoverflow.com/questions/682367/good-python-modules-for-fuzzy-string-comparison
编辑:一些示例代码:
import Levenshtein
base_strings = [
"R Deep Transverse Metatarsal Ligament 4 GEODE",
"R Distal JointCapsule 1 GEODE",
"R Dorsal Calcaneocuboid Ligament GEODE",
"R Dorsal Carpometacarpal Ligament 2 GEODE",
"R Dorsal Cuboideavicular Ligament GEODE",
"R Dorsal Tarsometatarsal Ligament 5 GEODE",
"R Elbow Capsule GEODE",
"R F Distal JointCapsule 1 GEODE",
"R Fibular Collateral Bursa GEODE",
"R Fibular Collateral Ligament GEODE",
"R Fibular Ligament GEODE"
]
def main():
print("Medical term matcher:")
while True:
t = raw_input('Match what? ').strip()
if len(t):
print("Best match: {}".format(sorted(base_strings, key = lambda x: Levenshtein.ratio(x, t), reverse=True)[0]))
else:
break
if __name__=="__main__":
main()
实际输出:
Medical term matcher:
Match what? R De Me Li
Best match: R Deep Transverse Metatarsal Ligament 4 GEODE
Match what? Fi Colla
Best match: R Fibular Collateral Bursa GEODE
Match what? bow ODE
Best match: R Elbow Capsule GEODE
Match what?
编辑2: “如果有多个答案,则应显示所有答案”-基本字符串在不同程度上都是答案。 那么,问题是您要使用哪种相似度截止值? 也许像“所有答案至少比最佳匹配的答案好90%”?
当所有粒子(在输入中用空格分隔的字符串段)都出现在结果中时,以下代码会使您想考虑“匹配”。 我在示例中使用了循环,但是您当然应该将其修改为使用raw_input
。
尽管它使用了正则表达式(允许有多个空格),但主要使用的功能是以下if particle in line
的if particle in line
:
import re
entry = """R Deep Transverse Metatarsal Ligament 4 GEODE
R Distal JointCapsule 1 GEODE
R Dorsal Calcaneocuboid Ligament GEODE
R Dorsal Carpometacarpal Ligament 2 GEODE
R Dorsal Cuboideavicular Ligament GEODE
R Dorsal Tarsometatarsal Ligament 5 GEODE
R Elbow Capsule GEODE
R F Distal JointCapsule 1 GEODE
R Fibular Collateral Bursa GEODE
R Fibular Collateral Ligament GEODE
R Fibular Ligament GEODE
"""
searches = """R De Me Li
Fi Colla
bow ODE"""
for search in searches.split('\n'):
print search, ':'
termlist = re.split('\s', search)
for line in entry.split('\n'):
match = True
for term in termlist:
if not term in line:
match = False
if match:
print '\t', line
print
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.