web-dev-qa-db-ja.com

リスト内包表記でre matchオブジェクトを使用する方法

私は文字列のリストからしこりを取り出して別のリストとして返す関数を持っています:

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')]
41
_[m.group(1) for l in lines for m in [regex.search(l)] if m]
_

「トリック」はfor m in [regex.search(l)]部分です。つまり、リスト内包で複数回使用する必要がある値を「割り当てる」方法です。このような句を追加して、オブジェクトを「繰り返し」ます「それに割り当てたい」1つの値を含む単一項目リストの上に。一部の人は、これをスタイル的に疑わしいと考えていますが、私はそれが時々実用的だと感じています。

70
Alex Martelli
return [m.group(1) for m in (re.search(regex, l) for l in lines) if m]

少し短くできます

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

すべてを1行に入れることもできますが、それはすべての行を2回一致させる必要があることを意味し、少し効率が悪くなります。

7
Wolph

_Python 3.8_の開始、および 代入式(PEP 572) (_:=_演算子)の導入により、複数の呼び出しを回避するためにリスト内包内でローカル変数を使用することが可能になりました同じ式の倍:

_# items = ["foo", "bar", "baz", "qurx", "bother"]
[(x, match.group(1)) for x in items if (match := re.compile('(a|r$)').search(x))]
# [('bar', 'a'), ('baz', 'a'), ('bother', 'r')]
_

この:

  • re.compile('(a|r$)').search(x)の評価に変数matchNoneまたはMatchオブジェクトのいずれか)として名前を付けます。
  • このmatch名前付き式を使用して(NoneまたはMatchのいずれか)、一致しない要素を除外します
  • そして、最初のグループ(match.group(1))を抽出することにより、マップされた値でmatchを再利用します。
1
Xavier Guihot