正则表达式:搜索包含多个部分的多个单词

2024-04-28 21:44:32 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图实现搜索一组包含多个部分的多个单词。 例如,我们有这些医学术语。在

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跖骨深横韧带4 GEODE”

例如,“Fi Colla”==>;“R腓侧副囊GEODE”,“R腓侧副韧带GEODE”

例如,“bow-ODE”==>;“R肘部胶囊GEODE”

也就是说,即使用户输入单词的某些部分,它也应该找到答案。 如果有多个答案,它应该显示所有答案。 我提前感谢你的帮助。在

补充)哦。。我忘了什么。在

例如,“ral lar”==>;不应显示“R腓骨侧支囊GEODE”或“R腓侧副韧带GEODE”,因为应考虑查询词的顺序。在

另外,查询词之间的空格表示每行(数据库)的不同单词。在

查询词的顺序应与每行(数据库)中的字相同, 但是查询词可以比数据库词短。在

例如,“R De Me 4”==>;“R跖骨深横韧带4 GEODE” 我们可以看到'跖骨'和'韧带'包括'我',但第一次匹配'跖骨'是好的,4将被搜索。在

另外,不同的查询词组合可以返回相同的结果。在

例如

'Car'==>;'R腕掌背侧韧带2 GEODE'

“Do Car”==>;“R腕掌背侧韧带2 GEODE”

'R Do Carp'==>;'R腕掌背侧韧带2 GEODE'

注意:不区分大小写。在


Tags: 答案gt数据库单词ligament韧带geodedistal
3条回答

不是真正的“正则表达式”问题;您应该考虑字符串的模糊比较,即Levenshtein distance或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()

实际产量:

^{pr2}$

编辑2:“如果有多个答案,它应该显示全部”—基本字符串是不同程度的所有答案。那么,问题是,你想要使用什么样的相似度临界值;也许是“所有答案至少是最佳匹配的90%”之类的东西?在

一个简单的Python式解决方案,它按回答完成任务,并且不区分大小写:

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,它不区分大小写。在

然后,它可以按预期工作,您可以尝试使用底座:

^{pr2}$

一些示例请求:

>>> 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']不匹配,而{}将匹配)。在

注意:我不认为模糊搜索在这里有多大帮助,至少一开始是,因为它是基于诸如Levenshtein(编辑距离)这样的距离的,它在比如“Fi”和“Fibular”(一个词的距离是5。。。在35%的情况下,我不是苏尔这是一个好主意匹配。。。如果您非常确定请求中只包含完整的单词,并且可能会有少量的错误输入,则可以使用它)

您可以使用标准发行版中的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)

印刷品:

^{pr2}$

结合cblab's answer结合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

相关问题 更多 >