2010-03-12 79 views
37

我有一個函數從字符串列表挑選出腫塊,並返回它們作爲另一個列表使用重新匹配對象:如何在列表理解

def filterPick(lines,regex): 
    result = [] 
    for l in lines: 
     match = re.search(regex,l) 
     if match: 
      result += [match.group(1)] 
    return result 

有沒有辦法重新制定這個作爲一個列表理解?顯然這是相當清楚的;只是好奇。


感謝那些貢獻者,特別提到@Alex。這裏是我最終結果的簡明版本;正則表達式匹配方法傳遞到filterPick作爲「前懸掛」參數:

import re 

def filterPick(list,filter): 
    return [ (l, m.group(1)) for l in list for m in (filter(l),) if m] 

theList = ["foo", "bar", "baz", "qurx", "bother"] 
searchRegex = re.compile('(a|r$)').search 
x = filterPick(theList,searchRegex) 

>> [('bar', 'a'), ('baz', 'a'), ('bother', 'r')] 

回答

66
[m.group(1) for l in lines for m in [regex.search(l)] if m] 

的「絕招」是for m in [regex.search(l)]的一部分 - 這就是你如何「分配」,你需要使用一個值不止一次,在列表理解中 - 添加一個這樣的子句,其中的對象「遍歷」包含您想要「分配」給它的一個值的單個項目列表。有些人認爲這在風格上可疑,但我覺得有時候很實用。

+1

亞歷克斯,我喜歡那樣;感謝和+1。我有一些相當繁重的工作來處理這段代碼 - 我是否應該擔心設置和拆除「虛擬迭代器」的額外開銷?順便說一句,我贊成「稍後優化」的原則。 – 2010-03-13 00:12:57

+1

@Brent,對於搜索調用,「虛迭代器」應該可以忽略不計;一個較小的優化是使用'(regex.search(l),'''代替'[regex.search(l)]'(我發現它更易讀,但速度更慢 - 我認爲你不可能是因爲你實際上正在調用模塊的're.search'函數,而不是re對象的方法。將'regex.search'作爲listcomp之外的綁定方法拉動是另一個次要但有用的優化,順便提一下, – 2010-03-13 01:15:07

+0

as當我看到你的答案時,我意識到使用re.search並不是最好的方法,你能否澄清一下你如何「將regex.search作爲listcomp之外的綁定方法」?我真的很感激你對listcomp和Python noob的耐心等待 – 2010-03-13 10:08:31

9
return [m.group(1) for m in (re.search(regex, l) for l in lines) if m] 
7

它可以縮短一點

def filterPick(lines, regex): 
    matches = map(re.compile(regex).match, lines) 
    return [m.group(1) for m in matches if m] 

你可以把它全部在同一行,但也意味着你將不得不每行曾兩次將是一個有點低效率的匹配。

+2

不需要每行兩次匹配,請參閱我的答案。 – 2010-03-12 23:59:27

+0

事實上,你的答案是更清潔,從我+1 +1 – Wolph 2010-03-13 00:01:23

-13
>>> "a" in "a visit to the dentist" 
True 
>>> "a" not in "a visit to the dentist" 
False 

,也可用於你正在追捕列表中的

'P = 'A', 'B' 搜索查詢, 'C'

'B' 的P`返回true

+1

這是如何回答這個問題? – 2012-11-17 19:20:38

+0

這個問題可能會提供一個比re更好的方法來檢查列表中的輸入,但是如果你不想grep結果,那麼這種方法不起作用。 U總是可以爲重新輸出做一個簡單的循環。手動操作比使用同樣功能的功能差異不大 – erm3nda 2016-05-17 16:41:08