2013-04-30 8 views
5

私はジェネレータをビルドする必要があり、私はこれを1行に短縮する方法を探していました。私は列挙しようとしましたが、うまくいきませんでした。このPythonジェネレータ表現を短縮する方法はありますか?

counter=0 
for element in string: 
    if function(element): 
     counter+=1 
     yield counter 
    else: 
     yield counter 
+1

'counter = 0'が欠けていますか、これは何かの周りのクロージャーになっていますか? 'counter'は外側のコードにありますか? – abarnert

+0

Pythonのどのバージョン? – Blender

+0

いいえ、私はそれを最初から除外しましたが、私はそれを含めました。 – garlfd

答えて

6
counter=0 
for element in string: 
    counter+=bool(function(element)) 
    yield counter 

function()TrueFalse1、および0以外の戻り値を持つことができる場合

bool()呼び出しが必要なだけです。

4

あなたが行うことができますPythonの3を、使用している場合:

from itertools import accumulate 

yield from accumulate(1 if function(x) else 0 for x in string) 

私はSimeon Visser's answerを使用すると思いますが。これは短いかもしれませんが、コードが何をしているかはすぐに分かりません。

+0

@jamylak:最後に 'counter'変数はありません。 – Blender

+0

'function'が0と1を明示的に返さないかぎり、これは機能しません。返り値が' None'や文字列の場合は、 'TypeError'がすべて返されます。 'True'と' False'を返しても、最初の値は '0'ではなく' False'になります。 – abarnert

+0

"私は' accumulate'がブール値を返すと仮定しているのかどうかはわかりません。イテレータを返します。そして、それはあなたがそれを与える追加可能な型(あるいは、あなたがそれを与える型を加えた結果の上にあります。全く同じではありません。例えば、 'False + True == 1'、または古いPython、 '(1 << 31)+(1 << 31)=(1L << 32))。 – abarnert

3

あなたはそれを短縮することができます:(はい、int型にブール値を追加することが1Falseた正確Trueあるかのように動作する0た)

counter=0 
for element in string: 
    if function(element): 
     counter+=1 
    yield counter 
+0

私は実行カウントを保つ必要があるので、私はelse文も同様に生成する必要があります。 – garlfd

+2

@garlfd:これは文字列内のすべての要素でも発生しますが、一部の要素に対してのみ更新されます。 –

4

まず、あなたがfunction戻り値イテレータに文字列を変換することができます。

truths = (function(x) for x in string) 

その後、あなたは0と1にそれらをマッピングすることができます

onesandzeroes = (1 if function(x) else 0 for x in string) 

そしてaccumulateそれらを:

running = itertools.accumulate(1 if function(x) else 0 for x in string) 

ドキュメントノートには、accumulateが追加されましたPython 3.2。 2.xを使用している場合は、ドキュメントから「等価」レシピをコピーして貼り付けることができます。 (3.0-3.1を使用している場合は同じことができますが、その場合はアップグレードするだけです)

関連する問題