web-dev-qa-db-ja.com

ブレークリストの理解

条件に基づいてリストの理解を破るにはどうすればよいですか?たとえば、番号412 見つかった?

コード:

numbers = [951, 402, 984, 651, 360, 69, 408, 319, 601, 485, 980, 507, 725, 547, 544,
           615, 83, 165, 141, 501, 263, 617, 865, 575, 219, 390, 984, 592, 236, 105, 942, 941,
           386, 462, 47, 418, 907, 344, 236, 375, 823, 566, 597, 978, 328, 615, 953, 345, 399,
           162, 758, 219, 918, 237, 412, 566, 826, 248, 866, 950, 626, 949, 687, 217, 815, 67,
           104, 58, 512, 24, 892, 894, 767, 553, 81, 379, 843, 831, 445, 742, 717, 958, 609, 842,
           451, 688, 753, 854, 685, 93, 857, 440, 380, 126, 721, 328, 753, 470, 743, 527]

even = [n for n in numbers if 0 == n % 2]

機能的には、これが何をすべきかを推測することができます:

even = [n for n in numbers if 0 == n % 2 and break if n == 412]

I 本当に好む:

  • ワンライナー
  • itertoolsのような他の派手なライブラリはありません。可能な場合は「純粋なpython」(読み取り:ソリューションはimportステートメントなどを使用しないでください)
49
Flavius
even = [n for n in numbers[:None if 412 not in numbers else numbers.index(412)] if not n % 2] 

上記のF.J.のコードを取得し、412がリストにあるかどうかを確認するために3項を追加しました。それでも「1つのライナー」であり、412がリストにない場合でも機能します。

14

関数を使用してStopIterationlistを上げてキャッチします。

>>> def end_of_loop():
...     raise StopIteration
... 
>>> even = list(end_of_loop() if n == 412 else n for n in numbers if 0 == n % 2)
>>> print(even)
[402, 984, 360, 408, 980, 544, 390, 984, 592, 236, 942, 386, 462, 418, 344, 236, 566, 978, 328, 162, 758, 918]

不平を言う人にとっては、それはワンライナーではありません:

even = list(next(iter(())) if n == 412 else n for n in numbers if 0 == n % 2)

不満を言う人にとっては、それはハック的であり、本番コードで使用すべきではありません。まあ、あなたは正しいです。 間違いなく

53
WolframH

ジェネレーター式はitertools.takewhile()と一緒に使用できます。

even_numbers = (n for n in numbers if not n % 2)
list(itertools.takewhile(lambda x: x != 412, even_numbers))

編集importsを使用しないという要件に気付きました。とにかく、私はこの答えをここに残します。

43
Sven Marnach

412が間違いなくリストに含まれる場合は、これを使用できます。

_even = [n for n in numbers[:numbers.index(412)] if not n % 2]
_

結果に412を含めたい場合は、スライスにnumbers[:numbers.index(412)+1]を使用します。

スライスのために、これはitertoolsやforループソリューションよりも効率が悪い(少なくともメモリに関して)ことに注意してください。

14
Andrew Clark

リスト表示(リスト内包表記を含む)の構文は次のとおりです。 http://docs.python.org/reference/expressions.html#list-displays

ご覧のとおり、特別なwhileまたはuntil構文はありません。最も近いものは次のとおりです。

even_numbers = (n for n in numbers if 0 == n % 2)
list(itertools.takewhile(lambda x: x != 412, even_numbers))

(私がこれを入力している間に投稿されたSven Marnachの回答から取られたコード)。

4
Marcin

end条件の助けを借りて、_breaking in list comprehension_を解くための別の卑劣な1行のソリューション。

numbers.index(412)を使用せずに、おそらく少し高速ですか?

_even = [n for end in [[]] for n in numbers
        if (False if end or n != 412 else end.append(42))
        or not end and not n % 2]
_

注:これは悪い考えです。 ただの楽しみのために:)

@WolframHが言ったように:

不満を言う人にとっては、それはハック的であり、本番コードで使用すべきではありません。まあ、あなたは正しいです。 間違いなく

0
recnac