2009-11-03 28 views
9

我有一個庫文件名列表,需要根據正則表達式進行篩選,然後從匹配的列表中提取版本號。這是做了明顯的方式:Python列表篩選和轉換

libs = ['libIce.so.33', 'libIce.so.3.3.1', 'libIce.so.32', 'libIce.so.3.2.0'] 
versions = [] 
regex = re.compile('libIce.so\.([0-9]+\.[0-9]+\.[0-9]+)') 
for l in libs: 
    m = regex.match(l) 
    if m: 
     versions.append(m.group(1)) 

產生以下列表:

['3.3.1', '3.2.0'] 

可是我覺得,循環不是很'Python的風格和感覺它應該是可以更換「爲'循環上面的一些智能單線。 建議?

回答

19

列表理解如何?

In [5]: versions = [m.group(1) for m in [regex.match(lib) for lib in libs] if m] 
In [6]: versions 
Out[6]: ['3.3.1', '3.2.0'] 
5

你可以這樣做:

versions = [m.group(1) for m in [regex.match(l) for l in libs] if m] 

我不認爲這是非常具有可讀性,雖然...

也許這是分兩步完成的更加清晰:

matches = [regex.match(l) for l in line] 
versions = [m.group(1) for m in matches if m] 
0

你真的不需要打擾你的簡單情況下的正則表達式

>>> libs = ['libIce.so.33', 'libIce.so.3.3.1', 'libIce.so.32', 'libIce.so.3.2.0'] 
>>> libs 
['libIce.so.33', 'libIce.so.3.3.1', 'libIce.so.32', 'libIce.so.3.2.0'] 
>>> for i in libs: 
... print i.split("so.") 
... 
['libIce.', '33'] 
['libIce.', '3.3.1'] 
['libIce.', '32'] 
['libIce.', '3.2.0'] 
>>> for i in libs: 
... print i.split("so.")[-1] 
... 
33 
3.3.1 
32 
3.2.0 
>>> 

進一步檢查以獲得「點」的人。

1

對於使用循環標準,沒有什麼不是pythonic。但是,您可以使用map()函數根據針對列表中每個項目運行的函數的結果生成新列表。

0

這個怎麼樣:

import re 

def matches(regexp, list): 
    'Regexp, [str] -> Iterable(Match or None)' 
    return (regexp.match(s) for s in list) 

libs = ['libIce.so.33', 'libIce.so.3.3.1', 'libIce.so.32', 'libIce.so.3.2.0'] 
regexp = re.compile('libIce.so\.([0-9]+\.[0-9]+\.[0-9]+)') 
versions = [m.group(1) for m in matches(regexp, libs) if m is not None] 

>>> print versions 
['3.3.1', '3.2.0'] 
0

一個我能想到的辦法是結合「地圖」和列表理解。
的解決方案看起來如下:

import re 
libs = ['libIce.so.33', 'libIce.so.3.3.1', 'libIce.so.32', 'libIce.so.3.2.0'] 
versions = [] 

regex = re.compile('libIce.so\.([0-9]+\.[0-9]+\.[0-9]+)') 

def match(s): 
    m = regex.match(s) 
    if m: 
     return m.group(1) 

versions = [x for x in map(match,libs) if x] 

8

還有一個一個班輪只是爲了顯示其他方式(我也正則表達式有點清洗):

regex = re.compile(r'^libIce\.so\.([0-9]+\.[0-9]+\.[0-9]+)$') 
sum(map(regex.findall, libs), []) 

但請注意,你的原始版本比所有建議更具可讀性。值得改變嗎?

+1

感謝'findall'和'sum'! 關於可讀性 - 已經習慣了所有的stl和boost算法:) – 2009-11-03 20:26:44

+0

由於某種原因,這一個比我接受/ upvoted的答案對我更有意義。 – 2014-10-21 14:35:29