ネストしたdictをマージしたかったのだけど、適切な記事が全く見当たらない。
とりあえずdictをつくる。
dict1={"depth1_a":"x1a","depth1_b":"x1b","depth2_1":{"depth2_a":"x2a","depth2_b":"x2b"},"depth3_1":{"depth3_2":{"depth3_3_a":"x33a","depth3_3_b":"x33b"}}}dict2={"depth1_a":"y1a","depth1_c":"y1c","depth2_1":{"depth2_a":"y2a","depth2_c":"y2c"},"depth3_1":{"depth3_2":{"depth3_3_a":"y33a","depth3_3_c":"y33c"}}}
結果として欲しいのは、"depthx_a"はdict2の値で上書きされる、"depthx_b"と"depthx_c"は両方とも残る、というものです。
複数の辞書のマージ方法いろいろなどを参考に幾つか試してみたのですが、ネストの二段階目以降で"depthx_b"が消えます。
dict1.update(dict2)print(dict1){"depth1_a":"y1a","depth1_b":"x1b","depth2_1":{"depth2_a":"y2a","depth2_c":"y2c"},"depth3_1":{"depth3_2":{"depth3_3_a":"y33a","depth3_3_c":"y33c"}},"depth1_c":"y1c"}
ネストの一段階目にあるdepth1_a/depth1_b/depth1_cは想定通りになりましたが、それ以外は中身を見に行かずにキーで上書きされてしまいました。
Python3.3からはChainMapというのがあるらしいので試してみます。
fromcollectionsimportChainMapdict_map=ChainMap(dict1,dict2)dict(dict_map){"depth1_a":"y1a","depth1_c":"y1c","depth2_1":{"depth2_a":"y2a","depth2_c":"y2c"},"depth3_1":{"depth3_2":{"depth3_3_a":"y33a","depth3_3_c":"y33c"}},"depth1_b":"x1b"}
はいだめー。
結局最終的に自力でやるしかないのかよ、めんどくさいなあ、などと彷徨ってたらdictknife.deepmergeとかいうのを見つけました。
名前からして期待しかない。
fromdictknifeimportdeepmergedeepmerge(dict1,dict2){"depth1_a":"y1a","depth1_b":"x1b","depth2_1":{"depth2_a":"y2a","depth2_b":"x2b","depth2_c":"y2c"},"depth3_1":{"depth3_2":{"depth3_3_a":"y33a","depth3_3_b":"x33b","depth3_3_c":"y33c"}},"depth1_c":"y1c"}
これだよ俺の求めていたものは!
ただ残念ながら異なる型を突っ込んだ時の挙動が微妙です。"depth3_3_a": None
みたいにリテラル値にNoneを突っ込んだら上書きされてNoneになるのですが、ネストの枝そのものを削除したくて"depth3_2": None
としたら単に無視されました。
それならばと"depth3_2": ""
にしたらエラーになりました。
残念。
しかしこのdeepmerge、日本語情報が全くさっぱりびっくりするほど出てこないな。
便利なのでみんなも使うといいと思います。