私は文字列のリストからしこりを取り出して別のリストとして返す関数を持っています:
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')]
_[m.group(1) for l in lines for m in [regex.search(l)] if m]
_
「トリック」はfor m in [regex.search(l)]
部分です。つまり、リスト内包で複数回使用する必要がある値を「割り当てる」方法です。このような句を追加して、オブジェクトを「繰り返し」ます「それに割り当てたい」1つの値を含む単一項目リストの上に。一部の人は、これをスタイル的に疑わしいと考えていますが、私はそれが時々実用的だと感じています。
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回一致させる必要があることを意味し、少し効率が悪くなります。
_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)
の評価に変数match
(None
またはMatch
オブジェクトのいずれか)として名前を付けます。match
名前付き式を使用して(None
またはMatch
のいずれか)、一致しない要素を除外しますmatch.group(1)
)を抽出することにより、マップされた値でmatch
を再利用します。