4

重複の可能性:
Python: 述語に一致するシーケンス内の最初の要素を見つける

次の制御フロー パターンをカプセル化する Python 標準ライブラリに高次関数はありますか?

>>> def find(pred, coll):
...   for x in coll:
...     if pred(x):
...       return x
... 
>>> find(lambda n : n % 2 == 0, [3, 5, 8, 9, 6])
8
>>> find(lambda n : n % 2 == 0, [3, 5, 7, 9, 6])
6
>>> find(lambda n : n % 2 == 0, [3, 5, 7, 9, 1])
4

4 に答える 4

11

ifilterとを組み合わせisliceて、最初に一致する要素だけを取得できます。

>>> list(itertools.islice(itertools.ifilter(lambda n: n % 2 == 0, lst), 1))
[8]

ただし、これは、投稿した元のコードよりも読みやすく、優れているとは思いません。ただし、関数にラップすると、はるかに優れたものになります。そして、 1 つの要素のみを返すため、もうnext必要ありません。islice

def find(pred, iterable):
    return next(itertools.ifilter(pred, iterable), None)

None要素が見つからなかった場合に返されます。

ただし、ループごとに述語関数の呼び出しがかなり遅くなります。代わりに、リスト内包表記またはジェネレーター式の使用を検討してください。

>>> next((x for x in lst if x % 2 == 0), None)
8
于 2012-10-17T07:11:37.817 に答える
4

itertools.ifilter()結果のイテラブルの最初の要素を取得するだけで、これを行うことができます。

itertools.ifilter(pred, col1).next()

同様に、ジェネレーター オブジェクトも同様です (ここでも、結果のジェネレーターから最初の項目を取り出します)。

(i for i in col1 if i % 2 == 0).next()

これらは両方とも遅延評価されるため、述語を満たす最初の要素に到達するために必要なだけの入力 iterable のみを評価します。StopIteration述語に一致するものがない場合は、例外が発生することに注意してください。next()代わりにビルトインを使用することで、これを回避できます。

next((i for i in col1 if i % 2 == 0), None)
于 2012-10-17T07:12:11.687 に答える
2

私は頭の中でそのような関数を知りませんが、ジェネレーター式を使用して最初の結果を取得することができます。

x = (x for x in [3,5,8,9,6] if (lambda n: n % 2 == 0)(x))
y = x.next()

あるいは単に

y = (x for x in [3,5,8,9,6] if (lambda n: n % 2 == 0)(x)).next()
于 2012-10-17T07:16:10.543 に答える
2
(x for x in coll if pred(x)).next()

StopIterationアイテムが見つからない場合に発生します (特に が有効な戻り値である場合は、 を返すよりも好ましい場合NoneNoneあります)。

于 2012-10-17T07:16:20.567 に答える