Python組み込み関数、first(iterable)
およびany(iterable)
にいくらか似ている]にall(iterable)
がない理由があるのではないかと思っています。 (どこかstdlibモジュールに隠れているかもしれませんが、itertools
には表示されません。)first
は、短絡発生器の評価を実行して、不要な(および潜在的に無限の数of)操作を回避できます;すなわち.
def identity(item):
return item
def first(iterable, predicate=identity):
for item in iterable:
if predicate(item):
return item
raise ValueError('No satisfactory value found')
このようにして、次のようなことを表現できます。
denominators = (2, 3, 4, 5)
lcd = first(i for i in itertools.count(1)
if all(i % denominators == 0 for denominator in denominators))
ジェネレーターが終了しないため、その場合は明らかにlist(generator)[0]
を実行できません。
または、一致する正規表現の束がある場合(すべてが同じgroupdict
インターフェースを持っている場合に便利です):
match = first(regex.match(big_text) for regex in regexes)
list(generator)[0]
を避け、正の一致で短絡することにより、多くの不必要な処理を節約できます。
イテレータがある場合は、そのnext
メソッドを呼び出すだけです。何かのようなもの:
In [3]: (5*x for x in xrange(2,4)).next()
Out[3]: 10
「first」と呼ばれるPypiパッケージ があり、これを行います:
>>> from first import first
>>> first([0, None, False, [], (), 42])
42
たとえば、最初の奇数を返すために使用する方法は次のとおりです。
>> first([2, 14, 7, 41, 53], key=lambda x: x % 2 == 1)
7
Trueであるかどうかに関係なく、イテレータから最初の要素を返すだけの場合は、次のようにします。
>>> first([0, None, False, [], (), 42], key=lambda x: True)
0
これは非常に小さなパッケージです。この関数のみが含まれ、依存関係はなく、Python 2および3で動作します。単一のファイルなので、インストールする必要さえありません。それを使用します。
実際、ここにソースコードのほとんどがあります(バージョン2.0.1から、MITライセンス)でリリースされたHynek Schlawackによる):
def first(iterable, default=None, key=None):
if key is None:
for el in iterable:
if el:
return el
else:
for el in iterable:
if key(el):
return el
return default
類似の質問 を最近尋ねました(今ではこの質問の複製としてマークされています)。私の懸念は、ジェネレーターの最初の真の値を見つける問題を解決するために組み込みonlyを使用したかったということでもありました。私自身の解決策はこれでした:
x = next((v for v in (f(x) for x in a) if v), False)
最初の正規表現一致(最初の一致パターンではない!)を見つける例では、これは次のようになります。
patterns = [ r'\d+', r'\s+', r'\w+', r'.*' ]
text = 'abc'
firstMatch = next(
(match for match in
(re.match(pattern, text) for pattern in patterns)
if match),
False)
(パターンだけが返された場合に行うように)述部を2回評価せず、内包表記でローカルのようなハックを使用しません。
しかし、ロジックが1つだけを使用するように指示する場所にネストされた2つのジェネレーターがあります。したがって、より良い解決策はニースでしょう。
Itertoolsには「スライス」イテレーターがあります。 Pythonでよく知っているスライス操作をエミュレートします。あなたが探しているのはこれに似たものです:
myList = [0,1,2,3,4,5]
firstValue = myList[:1]
イテレータにitertoolsを使用する同等のもの:
from itertools import islice
def MyGenFunc():
for i in range(5):
yield i
mygen = MyGenFunc()
firstValue = islice(mygen, 0, 1)
print firstValue
あなたの質問にはあいまいさがあります。 firstの定義と正規表現の例は、ブールテストがあることを意味します。しかし、分母の例には明示的にif節があります。そのため、各整数が偶然に一致するのは偶然です。
Nextとitertools.ifilterの組み合わせは、あなたが望むものを提供するように見えます。
match = next(itertools.ifilter(None, (regex.match(big_text) for regex in regexes)))
Haskellは、関数take
(または部分関数take 1
、技術的に)。 Python Cookbook Haskellのtake
、takeWhile
、およびdrop
と同じ機能を実行するジェネレータラッパーが記述されています。
しかし、それが組み込みではない理由については、あなたの推測は私のものと同じくらい良いです。