2012-06-07 82 views
0

我試圖執行搜索包含多個部分的多個單詞集。例如,我們有這些醫療術語。正則表達式:搜索包含多個部分的多個單詞

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德我李」,那麼這應該找到「R跖骨深橫韌帶4 GEODE」

例如,「網絡科拉」 ==> 「R腓側副布爾薩GEODE」, 「R腓骨副韌帶GEODE」

例如, 「弓ODE」 ==> 「R彎頭膠囊GEODE」

也就是說,即使當用戶進入小號詞的部分,它應該找到答案。 如果有多個答案,它應該顯示全部。 我很感激你的幫助。

已添加)哦,我忘了一些東西。因爲查詢詞的順序應該被考慮,所以它不應該顯示「R腓骨側枝Bursa GEODE」或「R腓骨側副韌帶GEODE」。

另外,查詢詞之間的空格表示每行(數據庫)的不同詞。

查詢詞的順序應該與每行(數據庫)的詞相同,但是查詢詞可能比數據庫詞短。我們可以在這裏看到'跖骨'和'韌帶'包括'我',但是與​​'跖骨'的第一場比賽是'跖骨'很好,並且4將被搜索。

此外,查詢詞的不同組合可以返回相同的結果。

E,G。,

'汽車' ==> 'R背腕掌韌帶2 GEODE'

'做汽車' ==> 'R背腕掌韌帶2 GEODE'

'R Do Carp'==>'R背腕甲韌帶2 GEODE'

注意:不區分大小寫。

+0

我擡頭「的Python v2.7.3」的引用和網頁,並嘗試很多東西,但我無法做到這一點。基本上,我還不擅長正則表達式。 –

+1

如果有一個回答你的問題,也許你可以考慮「接受」它? – cedbeu

回答

4

您可以在標準分佈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's answer結合正則表達式與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 
+0

哇,包含電池! – steveha

+0

不錯!我喜歡它,當然我會重複使用! – cedbeu

1

不是真正的「正則表達式」問題;你應該看看字符串的模糊比較,即Levenshtein距離或差異。

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%和最佳匹配一樣好」?

1

下面的代碼表示您希望在將所有粒子(輸入中由空格分隔的字符串片斷)存在於結果中時考慮「匹配」。我在示例中使用了循環,但當然,您應該使其適用於使用raw_input

雖然它使用正則表達式(以允許多個空格),使用的主要特點是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 
+0

我有一種深深的感覺,認爲這段代碼可能更加pythonic,但至少它看起來很可讀:o) – heltonbiker

3

一個簡單的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不區分大小寫。

然後,它將按預期工作,你可以與底座嘗試:

>>> 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'將)。

注:我不認爲模糊搜索將有很大的幫助這裏,在第一至少,因爲它是基於距離的,如萊文斯坦的(編輯距離),這將是間非常大的,比方說, 'Fi'和'Fibular'(距離5英寸7 ...在35%的距離我不是一個好主意,匹配...你可以使用它,如果你是相當肯定的請求只包含可能有點錯誤輸入完整的單詞)

+0

根據「我不認爲模糊搜索會在這裏有所幫助」:只要編輯「fi」和「腓骨」小於「fi」和「背跖跖骨」​​之間,它的作品 - 它不一定是一個「好」的匹配,只是「比其他人好」。 –

+0

使用距離法,當您搜索'Car' - >'R Fibular Collat​​eral Bursa GEODE',現在'Do Car' - >'R肘膠囊GEODE','R Do Carp' - >'R肘膠囊GEODE'等,等等......然而,我們在一個非常小的數據集上。我不確定這是否是想要的行爲。當我們搜索'Car'時,它應該返回'R Carorstacarpal Ligament 2 GEODE','Do Car'或'R Do Carp'。不過,這是我理解問題的方式。 – cedbeu

+0

儘管如此,我認爲模糊搜索可以幫助改進更高級的搜索算法,並且具有堅實的全文搜索基礎。但它不是一個非常簡單的解決方案。但無論如何,difflib似乎是不可能重新發明輪子的好選擇。 – cedbeu