2009-11-03 9 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のスタイル」ではありません、交換することが可能であるべきと感じていることを感じますfor 'ループの上にいくつかのスマートな1つのライナー。 提案?

答えて

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] 

私はそれはしかし、非常に読みやすいではないと思う...

を多分それは明確には2つの段階で行われています:

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()関数を使用して、リスト内の各項目に対して実行された関数の結果に基づいて新しいリストを生成することができます。

この1についてどのように
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アルゴリズムでそれに使用されていました:) –

+0

何らかの理由で、これは受け入れられた/上書きされた答えよりもはるかに理にかなっています。 –

関連する問題