リストのフィルタリングおよび変換
-
13-09-2019 - |
質問
いリストの図書館のファイル名を必要とすることをフィルターに対し正規表現とその抽出バージョン番号から。これは明らかな方法が確立されてきてい:
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'ループ上の一部のスマートワン-ライナーう方に。
解決
どのようにリストの内包についてはどうですか?
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']
他のヒント
もう一つのワンライナーは、単に他の方法を(私も正規表現ビットをきれいにしました)表示します
regex = re.compile(r'^libIce\.so\.([0-9]+\.[0-9]+\.[0-9]+)$')
sum(map(regex.findall, libs), [])
しかし、あなたの元のバージョンは、すべての提案よりも読み取り可能であること、注意してください。変更することは価値がある?
あなたはこれを行うことができます:
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]
ループのための標準の使用についてのニシキヘビではないものは何もありません。しかし、あなたは新しいを生成するために、マップ()の機能を使用することができますリストの各項目に対して実行機能からの結果に基づいてリストます。
あなたが本当にあなたの単純なケースのための正規表現を気にする必要はありません。
>>> 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:
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']
私は考えることができ、
一つの方法は、「マップ」とリスト内包を組み合わせることでした。
解決策は、以下のようになります。
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]
始 Python 3.8
, の導入 課題の表現(PEP572) (:=
し、オペレーターを採用することも可能ですローカル変数内のリストの理解を避けるために呼び出しの結果の正規表現マッチング:
# libs = ['libIce.so.33', 'libIce.so.3.3.1', 'libIce.so.32', 'libIce.so.3.2.0']
# pattern = re.compile(r'libIce.so\.([0-9]+\.[0-9]+\.[0-9]+)')
[match.group(1) for lib in libs if (match := pattern.match(lib))]
# ['3.3.1', '3.2.0']
この:
- 名前の評価
pattern.match(lib)
変数としてmatch
(はどうしたらよいですかNone
またはre.Match
オブジェクト) - この
match
名前の表現場からNone
またはMatch
)フィルター出マッチング素子 - 再利用
match
にマップされた値を抽出しの最初のグループ(match.group(1)
).
所属していません StackOverflow