【python3】辞書形の要素全てに同じ処理を行いたい!

どーも!

たかぽんです!

今回はpythonのお話です...!

最近ブロックチェーンゲームのBOTをpythonで作っているのですが、ちょっと修正している際に困ったので、これを機に深掘りして調べておこうと思います...!

やりたいこと

さて、やりたいことなんですが...

pythonのディクショナリーというデータの要素全てに対して操作をしたかったんですね...

例えば...以下のようなデータがあったら...

dict = {
    "1": 1,
    "2": 2,
    "3": 3
}

全てのvalueを2倍にして以下のようにしたい...!

dict = {
    "1": 2,
    "2": 4,
    "3": 6
}

というのがやりたかったことです。

(2倍の部分は足し算なり割り算なり、簡単な操作ですね)

ぱっと見map関数とかでサクッとできるんじゃないの?と思うかもしれないですが...

どうも辞書形にはそういった類のメソッドがなさそうでした。

そのため、自分でなんとかするしかないと...

解決策

さて、それでは解決策を見ていきます...!

早速ですがコードをペタッ。

dict = {"1": 1,"2": 2,"3": 3}

def f(x):
  return x*2

doubled_dict = {k: f(v) for k, v in dict.items()}

print(dict) # {'1': 1, '2': 2, '3': 3}
print(doubled_dict) # {'1': 2, '2': 4, '3': 6}

大まかには上記のようになります。

簡単に説明をしておくと、"for k, v in dict.items()"にて、dictのkey, valueを取り出し、その値を都度"k : f(v)"という形で辞書を定義しています。

ここで、fを噛ませているので、関数の定義で二倍にしておけば、valueだけ二倍される感じですね。

正直pythonは行き当たりばったりで色々調べているので、いまだに辞書やリストどちらを使うべきかとか曖昧な部分もありますが、少しづつなれていきたいですね...

現状の理解だと連想配列的なkey,valueは辞書、単縦にvalueのみであればリストでいいんだろうなぁ...と思っています。

どちらにせよ、辞書だとvalue全体に同じ操作をする場合は一手間加えないと...みたいですね。

おまけ

最後に、ちょっと手元で色々確認したので、連想配列からkey, valueそれぞれのみ、どちらにも別の関数を試した例、リストでmapによって処理する場合を以下へ記載しておきます。

# dictionalyの場合
dict = {"1": 1,"2": 2,"3": 3}

def double(x):
    return x*2
def triple(x):
    return str(int(x)*3)

doubled_dict = {k: double(v) for k, v in dict.items()}

doubled_dict_only_key = {k for k, v in dict.items()}
doubled_dict_only_value = {double(v) for k, v in dict.items()}
doubled_dict_both = {triple(k): double(v) for k, v in dict.items()}

print(dict) # {'1': 1, '2': 2, '3': 3}
print(doubled_dict) # {'1': 2, '2': 4, '3': 6}
print(doubled_dict_only_key) # {'3', '2', '1'}
print(doubled_dict_only_value) # {2, 4, 6}
print(doubled_dict_both) # {'3': 2, '6': 4, '9': 6}

# リストの場合
original_list = [1, 2, 3]
doubled_list = list(map(double, original_list))

print(original_list) # [1, 2, 3]
print(doubled_list) # [2, 4, 6]

一点気をつけないといけないのが、keyを文字列で定義している場合、triple関数にて"return x*3"としてしまうと、文字列が3個と処理され下記のようになってしまったので、キャストでいい感じにしていますが、文字列の処理と数字の処理等の違いは気を付ける必要がありそうですね!

{'111': 2, '222': 4, '333': 6}

ただ、for文で返す値に対してそれぞれ別の関数を噛ませればvalueには全部この処理を、keyには別の処理をした上で辞書を作り直す...といったことも可能そうです。

おすすめの記事