Pythonで次のような2つの辞書型をマージしたいケースがありました。
dict_a = {
'A': 'A',
'B': {
'C':'C',
'D':'D',
'E': {
'F':'F',
'G':'G'
}
},
'H': ['I','J'],
'L': [{'M': 'M', 'N': 'N'}, {'O':'O'}]
}
dict_b = {
'A': 'a',
'B': {
'C':'c',
'E': {
'F':'f',
}
},
'H': ['k'],
'L': [{'N': 'n'}, {'P':'p'}]
}
マージする方法を調べていると、以下のようなやりかたがあります。
- 新規につくる方法
print(dict(dict_a, **dict_b))
実行結果はこうなります
{'B': {'C': 'c', 'E': {'F': 'f'}}, 'L': [{'N': 'n'}, {'P': 'p'}], 'A': 'a', 'H': ['k']}
しかし、実行結果をよく見ると、dict_a[‘B’][‘D’] や dict_a[‘B’][‘E’][‘G’] がなくなっています。 実行結果から考えると入れ子になっているところはマージしてくれないようです。 他にも調べてみましたが、いい感じにマージする方法がないようなので、実装しました。
import copy
dict_a = {
'A': 'A',
'B': {
'C':'C',
'D':'D',
'E': {
'F':'F',
'G':'G'
}
},
'H': ['I','J'],
'L': [{'M': 'M', 'N': 'N'}, {'O':'O'}]
}
dict_b = {
'A': 'a',
'B': {
'C':'c',
'E': {
'F':'f',
}
},
'H': ['k'],
'L': [{'N': 'n'}, {'P':'p'}]
}
def merge_list(a, b):
m = copy.copy(a)
for i, value in enumerate(b):
if isinstance(value, dict):
m[i] = merge_dict(a[i], b[i])
elif isinstance(value, list):
m[i] = merge_list(a[i], b[i])
else:
m.append(value)
return m
def merge_dict(a, b):
m = copy.copy(a)
for item in b:
if isinstance(b[item], dict):
m[item] = merge_dict(a[item], b[item])
elif isinstance(b[item], list):
m[item] = merge_list(a[item], b[item])
else:
m[item] = b[item]
return m
print(merge_dict(dict_a, dict_b))
実行結果
{'H': ['I', 'J', 'k'], 'B': {'E': {'F': 'f', 'G': 'G'}, 'D': 'D', 'C': 'c'}, 'A': 'a', 'L': [{'M': 'M', 'N': 'n'}, {'O': 'O', 'P': 'p'}]}
ほしい結果が得られました。 配列の扱いをどうするか難しいところですね。 辞書をマージする時はお気をつけください。
高橋克幸
新卒3年目で脱新人を目指してます。
フロントに興味を持ち始めた今日このごろ。
趣味は 麻雀 プログラミング 音楽。
運動不足を感じているため、ダンスを始めようかと思っています。