web-dev-qa-db-ja.com

リスト内包表記で「else」を使用することは可能ですか?

以下は、リストを理解しようとしたコードです。

table = ''
for index in xrange(256):
    if index in ords_to_keep:
        table += chr(index)
    else:
        table += replace_with

この理解にelseステートメントを追加する方法はありますか?

table = ''.join(chr(index) for index in xrange(15) if index in ords_to_keep)
182
Josh

構文a if b else cはPythonの三項演算子で、条件aが真の場合にbに評価されます。それ以外の場合は、cに評価されます。理解ステートメントで使用できます。

>>> [a if a else 2 for a in [0,1,0,3]]
[2, 1, 2, 3]

あなたの例では、

table = ''.join(chr(index) if index in ords_to_keep else replace_with
                for index in xrange(15))
295
Amber

リスト内包表記をフィルタリングしたくないelseが必要な場合は、すべての値を反復処理する必要があります。代わりにステートメントとしてtrue-value if cond else false-valueを使用し、最後からフィルターを削除できます。

table = ''.join(chr(index) if index in ords_to_keep else replace_with for index in xrange(15))
15
Michael Mrozek

pythonプログラミングのリスト内包表記でelseを使用するには、以下のスニペットを試してください。これで問題が解決します。スニペットはpython 2.7およびpython 3.5でテストされます。

obj = ["Even" if i%2==0 else "Odd" for i in range(10)]
8
Chitrank Dixit

はいelse内のPythonでlistを使用できますcomprehensionConditional Expression (「三項演算子」):

>>> [("A" if b=="e" else "c") for b in "comprehension"]
['c', 'c', 'c', 'c', 'c', 'A', 'c', 'A', 'c', 'c', 'c', 'c', 'c']

ここでは、括弧「()」は条件式を強調するためのものであり、必ずしも必要ではありません( Operator precedence )。

さらに、いくつかの式をネストできるため、elsesが増え、コードが読みにくくなります。

>>> ["A" if b=="e" else "d" if True else "x" for b in "comprehension"]
['d', 'd', 'd', 'd', 'd', 'A', 'd', 'A', 'd', 'd', 'd', 'd', 'd']
>>>

関連する注意事項として、内包表記の末尾に独自のif条件を含めることもできます。

>>> ["A" if b=="e" else "c" for b in "comprehension" if False]
[]
>>> ["A" if b=="e" else "c" for b in "comprehension" if "comprehension".index(b)%2]
['c', 'c', 'A', 'A', 'c', 'c']

条件s?はい、複数のifsが可能です。実際、複数のforsも可能です。

>>> [i for i in range(3) for _ in range(3)]
[0, 0, 0, 1, 1, 1, 2, 2, 2]
>>> [i for i in range(3) if i for _ in range(3) if _ if True if True]
[1, 1, 2, 2]

(単一の下線_は有効な変数名( identifier )です。ここでは、実際に使用されていないことを示すためにここで使用されています 。インタラクティブモードでは 特別な意味を持ちます

これを追加の条件式に使用することは可能ですが、実際には使用できません。

>>> [i for i in range(3)]
[0, 1, 2]
>>> [i for i in range(3) if i]
[1, 2]
>>> [i for i in range(3) if (True if i else False)]
[1, 2]

内包表記をネストして、「多次元」リスト(「配列」)を作成することもできます。

>>> [[i for j in range(i)] for i in range(3)]
[[], [1], [2, 2]]

最後になりましたが、内包表記はlistの作成に限定されません。つまり、elseifは、 set 内包表記でも同じように使用できます。

>>> {i for i in "set comprehension"}
{'o', 'p', 'm', 'n', 'c', 'r', 'i', 't', 'h', 'e', 's', ' '}

および dictionary 内包表記:

>>> {k:v for k,v in [("key","value"), ("dict","comprehension")]}
{'key': 'value', 'dict': 'comprehension'}

同じ構文が Generator Expressions にも使用されます:

>>> for g in ("a" if b else "c" for b in "generator"):
...     print(g, end="")
...
aaaaaaaaa>>>

Tupleの作成に使用できます( タプル内包表記はありません )。


6
handle

すばらしい答えですが、リスト理解のif/else部分では「pass」キーワードが機能しないという落とし穴に言及したかっただけです(上記の例に掲載)。

#works
list1 = [10, 20, 30, 40, 50]
newlist2 = [x if x > 30 else x**2 for x in list1 ]
print(newlist2, type(newlist2))

#but this WONT work
list1 = [10, 20, 30, 40, 50]
newlist2 = [x if x > 30 else pass for x in list1 ]
print(newlist2, type(newlist2))

これは、python 3.4で試行およびテストされています。エラーは次のとおりです。

newlist2 = [x if x > 30 else pass for x in list1 ]                                    
SyntaxError: invalid syntax

したがって、リスト内包表記のパスを避けるようにしてください

2
Plankton

また、リストの理解がこれを行うための最も効率的な方法であると結論付けるのは正しいでしょうか?

多分。リストの内包表記は、本質的に計算効率的ではありません。まだ線形時間で実行されています。

私の個人的な経験から:リスト内包表記(特にネストされたもの)を上記のforループ/リスト付加型構造に置き換えることにより、大きなデータセットを扱う際の計算時間を大幅に短縮しました。このアプリケーションでは、違いに気付くとは思いません。

1
Donald Miner