2012-05-22 68 views
3

我需要將列表的內容與給定模式匹配,並形成另一個列表,除了匹配之外,它將包含所有內容。意思是,我正在嘗試做一個排除列表。從列表中查找和排除多個匹配的邏輯

現在有了一個模式匹配,很容易。但對於更多的人來說,這變得棘手。

讓我們來看一個例子:

Lmain=[arc123, arc234,xyz111,xyz222,ppp999,ppp888] 

for count in range(len[Lmain]): 

    if Pattern matches Lmain[i]: 
       Pass 
    else:result.append(Lmain[i]) 

現在讓我們說模式=圓弧,我的結果將是

result = [xyz111,xyz222,ppp999,ppp888] 

這僅僅是一個邏輯,在這裏我將使用常規EXPR尋找匹配。

現在,如果我們有2種模式,然後在循環中使用上面的邏輯:

Pattern=['arc','xyz'] 

for pat in Pattern: 
     if pat matches Lmain[i]: 
      Pass 
     else:result.append(Lmain[i]) 

這會給我們錯誤的結果

result = [xyz111,xyz222,ppp999,ppp888,arc123,arc234,ppp999,ppp888] 

所以,你可以看到上面的邏輯只是不會工作。

我的計劃:

首先,我們發現排除列表第一圖案,這將給我們造成:

result = [xyz111,xyz222,ppp999,ppp888] 

對於第二個模式,我們需要將目光轉向上述結果。

if Pattern matches Result[i]: 
     Pass 
else:result_final.append(Result[i]) 

我想我們需要使用遞歸來實現上面的邏輯。現在我們該怎麼做? 另外我們不知道用戶將要輸入的模式數量。它可以是一個或多個。

任何人有任何邏輯思想,然後請分享。

+1

能否請您使用真正的Python代碼爲您的例子嗎? – geoffspear

回答

5

使用列表中理解和發電機的表達,並跳過建立一個排除列表的中間步驟,而直接建造最終名單:

>>> import re 
>>> Lmain=['arc123', 'arc234', 'xyz111', 'xyz222','ppp999','ppp888'] 
>>> Pattern=['arc','xyz'] 
>>> [x for x in Lmain if not any(re.search(y, x) for y in Pattern)] 
['ppp999', 'ppp888'] 
1
matched = False 
for pat in Pattern: 
    if pat patches Lmain[i]: 
     matched = True 
     break; 
if matched: 
    Pass 
else: 
    result.append(Lmain[i]) 
4
for item in lst: 
    if all(pat not in item for pat in patterns): 
     exclude_list.append(item) 

更換in,什麼是你的情況更合適(如item.startswith(pat)

如果有更多的比賽比非匹配,它應該是更有效地先找到比賽,並然後排除他們:

matches = [x for x in lst if any(x.startswith(p) for p in patterns)] 
exclude_list = list(set(lst).difference(matches)) 

另一個(也可能是最快)選項(在這裏組合與filter)使用正則表達式:

import re 
expr = '^(?!%s)' % '|'.join(patterns) 
exclude_list = filter(re.compile(expr).search, lst) 
+0

+1,也可以在單行中執行:'exclude_list = [item in item in lst if all(pat pat not in item for pat in patterns)]' – eumiro

+0

@eumiro,這是Wooble寫的,但我發現compr less在這種情況下可讀。 – georg