辞書内包表記でif / elseを使用するにはどうすればよいですか?


138

Python 2.7以降に次のようなものを作成する方法はありますか?

{ something_if_true if condition else something_if_false for key, value in dict_.items() }

私はあなたが 'if'だけで何でも作ることができることを知っています:

{ something_if_true for key, value in dict_.items() if condition}

4
@Marcinが言うように、a dictkey:value要素でできています。dictここではなく、aを構築していますsetset literalsを参照)。
mdeous

回答:


247

あなたはすでにそれを持っています:A if test else Bは有効なPython式です。示されているdict内包表記の唯一の問題は、dict内包表記の式の場所に、コロンで区切られた2つの式が必要なことです。

{ (some_key if condition else default_key):(something_if_true if condition
          else something_if_false) for key, value in dict_.items() }

最後のif句はフィルターとして機能します。これは、条件式を持つこととは異なります。


28
キーと値の両方にif-else条件を設定する必要がないことに言及する価値があります。たとえば、{(a if condition else b): value for key, value in dict.items()}動作します。
Jeremy Weirich

5
@JeremyWeirich必要がない場合は、どちらかにif-elseを設定する必要はありません。
Marcin

@Marcinキー部分に「if」のみを使用し、値部分に「if」と「else」の両方を使用することは可能ですか?
nithin11

14

@Marcinの回答はそれをすべてカバーしていますが、誰かが実際の例を見たい場合に備えて、以下に2つ追加します。

次のセットの辞書があるとしましょう

d = {'key1': {'a', 'b', 'c'}, 'key2': {'foo', 'bar'}, 'key3': {'so', 'sad'}}

そして、キーが文字列'a'が値に含まれているかどうかを示す新しい辞書を作成したい場合は、

dout = {"a_in_values_of_{}".format(k) if 'a' in v else "a_not_in_values_of_{}".format(k): v for k, v in d.items()}

これは

{'a_in_values_of_key1': {'a', 'b', 'c'},
 'a_not_in_values_of_key2': {'bar', 'foo'},
 'a_not_in_values_of_key3': {'sad', 'so'}}

今、あなたはこのような2つの辞書を持っているとしましょう

d1 = {'bad_key1': {'a', 'b', 'c'}, 'bad_key2': {'foo', 'bar'}, 'bad_key3': {'so', 'sad'}}
d2 = {'good_key1': {'foo', 'bar', 'xyz'}, 'good_key2': {'a', 'b', 'c'}}

そして、あなたは内のキーを交換したいd1のキーでd2あり、それぞれの値が同一であれば、あなたが行うことができます

# here we assume that the values in d2 are unique
# Python 2
dout2 = {d2.keys()[d2.values().index(v1)] if v1 in d2.values() else k1: v1 for k1, v1 in d1.items()}

# Python 3
dout2 = {list(d2.keys())[list(d2.values()).index(v1)] if v1 in d2.values() else k1: v1 for k1, v1 in d1.items()}

与える

{'bad_key2': {'bar', 'foo'},
 'bad_key3': {'sad', 'so'},
 'good_key2': {'a', 'b', 'c'}}

を使用した2番目の例ではd1d2私は取得しますAttributeError: 'dict_values' object has no attribute 'index'
アランカルヴィッティ

@alancalvitti:これを指摘してくれてありがとう!解決策はPython 2用であり、Python 3では機能しません。Python 3ソリューションも追加しました。
クレブ

3

場合は、あなたは持っているさまざまな条件マルチンの答えが進むべき道である@、キーと値のために評価するために。

あなたが持っている場合は、同じ条件のキーと値のために、あなたはより良いオフに発電式の給餌で(キー、値)タプルを構築するとしていますdict()

dict((modify_k(k), modify_v(v)) if condition else (k, v) for k, v in dct.items())

読みやすく、条件はキー、値ごとに1回だけ評価されます。

@Clebのセットの辞書を借りる例:

d = {'key1': {'a', 'b', 'c'}, 'key2': {'foo', 'bar'}, 'key3': {'so', 'sad'}}

あなたはサフィックスだけにしたいと仮定keysしてa、その中でvalue、あなたがしたいvalueような場合にはセットの長さに置き換えます。それ以外の場合、キーと値のペアは変更されません。

dict((f"{k}_a", len(v)) if "a" in v else (k, v) for k, v in d.items())
# {'key1_a': 3, 'key2': {'bar', 'foo'}, 'key3': {'sad', 'so'}}

0

辞書内包表記でif / elseを使用する別の例

私は自分のオフィス作業用のデータ入力デスクトップアプリケーションに取り組んでいます。そのようなデータ入力アプリケーションは、入力ウィジェットからすべてのエントリを取得し、検証などのさらなる処理または返す必要がある編集のためにディクショナリにダンプするのが一般的です選択したデータをファイルからエントリウィジェットなどに戻します。

従来のコーディングを使用した最初のラウンド(8行):

entries = {'name': 'Material Name', 'maxt': 'Max Working Temperature', 'ther': {100: 1.1, 200: 1.2}}

a_dic, b_dic = {}, {}

for field, value in entries.items():
    if field == 'ther':
        for k,v in value.items():
            b_dic[k] = v
        a_dic[field] = b_dic
    else:
        a_dic[field] = value
    
print(a_dic)
 {'name': 'Material Name', 'maxt': 'Max Working Temperature', 'ther': {100: 1.1, 200: 1.2}}”

2回目は、辞書内包表記を使用しようとしましたが、ループはまだそこにあります(6行):

entries = {'name': 'Material Name', 'maxt': 'Max Working Temperature', 'ther': {100: 1.1, 200: 1.2}}

for field, value in entries.items():
    if field == 'ther':
        b_dic = {k:v for k,v in value.items()}
        a_dic[field] = b_dic
    else:
        a_dic[field] = value
    
print(a_dic)
 {'name': 'Material Name', 'maxt': 'Max Working Temperature', 'ther': {100: 1.1, 200: 1.2}}”

最後に、1行の辞書内包表記(1行)を使用します。

entries = {'name': 'Material Name', 'maxt': 'Max Working Temperature', 'ther': {100: 1.1, 200: 1.2}}

a_dic = {field:{k:v for k,v in value.items()} if field == 'ther' 
        else value for field, value in entries.items()}
    
print(a_dic)
 {'name': 'Material Name', 'maxt': 'Max Working Temperature', 'ther': {100: 1.1, 200: 1.2}}”

私はpython 3.8.3を使用しています

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.