内包表記の(マップ)部分と (フィルター) 部分のlet
両方でスコープが使用可能で、スコープが.___ for..in
if ___
..for ___ in...
あなたの解決策、変更:
あなたの (判読できないことを認めているように) の解決策は[ (x,fx) for x,fx in ( (y,f(y) for y in iterable ) if fx ]
、最適化を記述する最も簡単な方法です。
主なアイデア: x をタプル (x,f(x)) に持ち上げます。
物事を行うための最も「pythonic」な方法はオリジナル[(x,f(x)) for x in iterable if f(x)]
であり、非効率性を受け入れると主張する人もいます。
ただし((y,fy) for y in iterable)
、これを頻繁に行う予定がある場合は、 を関数に分解できます。x,fx
より多くの変数にアクセスしたい場合(例: x,fx,ffx
)、すべてのリスト内包表記を書き直す必要があるため、これは悪いことです。x,fx
したがって、このパターンのみが必要であり、再利用する計画があることが確実にわかっていない限り、これは優れたソリューションではありません。
ジェネレータ式:
主なアイデア: ジェネレータ式のより複雑な代替手段を使用します: Python で複数行を記述できるようにするものです。
Pythonがうまく機能するジェネレーター式を使用することができます:
def xfx(iterable):
for x in iterable:
fx = f(x)
if fx:
yield (x,fx)
xfx(exampleIterable)
これは私が個人的に行う方法です。
メモ化/キャッシング:
主なアイデア: (悪用?) 副作用を使用しf
て、グローバルなメモ化キャッシュを作成して、操作を繰り返さないようにすることもできます。
これには多少のオーバーヘッドが発生する可能性があり、キャッシュのサイズとガベージ コレクションのタイミングに関するポリシーが必要です。したがって、これは、f をメモ化する他の用途がある場合、または f が非常に高価な場合にのみ使用する必要があります。しかし、それはあなたが書くことを可能にするでしょう...
[ (x,f(x)) for x in iterable if f(x) ]
f
...技術的に2回呼び出したとしても、高価な操作を2回実行することによるパフォーマンスへの影響なしに、最初に望んでいたように。次の例@memoized
にデコレータを追加できます(最大キャッシュ サイズなし)。これは、x がハッシュ可能 (数値、タプル、frozenset など) である限り機能します。f
ダミー値:
主なアイデア: クロージャで fx=f(x) をキャプチャし、リスト内包表記の動作を変更します。
filterTrue(
(lambda fx=f(x): (x,fx) if fx else None)() for x in iterable
)
ここで、filterTrue(iterable) は filter(None, iterable) です。リスト タイプ (2 タプル) が実際に可能である場合は、これを変更する必要がありますNone
。