辞書の辞書がマージされます
これは(特定の非一般性にもかかわらず)標準的な質問であるため、この問題を解決するための標準的なPythonのアプローチを提供します。
最も単純なケース:「葉は空の辞書で終わるネストされた辞書です」:
d1 = {'a': {1: {'foo': {}}, 2: {}}}
d2 = {'a': {1: {}, 2: {'bar': {}}}}
d3 = {'b': {3: {'baz': {}}}}
d4 = {'a': {1: {'quux': {}}}}
これは再帰の最も単純なケースであり、2つの単純なアプローチをお勧めします。
def rec_merge1(d1, d2):
'''return new merged dict of dicts'''
for k, v in d1.items(): # in Python 2, use .iteritems()!
if k in d2:
d2[k] = rec_merge1(v, d2[k])
d3 = d1.copy()
d3.update(d2)
return d3
def rec_merge2(d1, d2):
'''update first dict with second recursively'''
for k, v in d1.items(): # in Python 2, use .iteritems()!
if k in d2:
d2[k] = rec_merge2(v, d2[k])
d1.update(d2)
return d1
私は最初のものより2番目のものを好むと思いますが、最初のものの元の状態はその起源から再構築する必要があることを覚えておいてください。使い方は次のとおりです。
>>> from functools import reduce # only required for Python 3.
>>> reduce(rec_merge1, (d1, d2, d3, d4))
{'a': {1: {'quux': {}, 'foo': {}}, 2: {'bar': {}}}, 'b': {3: {'baz': {}}}}
>>> reduce(rec_merge2, (d1, d2, d3, d4))
{'a': {1: {'quux': {}, 'foo': {}}, 2: {'bar': {}}}, 'b': {3: {'baz': {}}}}
複雑なケース:「葉は他のタイプです:」
したがって、それらがディクテーションで終わる場合、それは最後の空のディクテーションをマージする単純なケースです。そうでなければ、それはそれほど簡単ではありません。文字列の場合、どのようにマージしますか?セットも同様に更新できるため、その扱いを与えることができますが、マージされた順序は失われます。では、注文は重要ですか?
したがって、より多くの情報の代わりに、最も単純なアプローチは、両方の値がdictでない場合に標準の更新処理を与えることです。つまり、2番目のdictの値がNoneで、最初の値がたくさんの情報を持つdict。
d1 = {'a': {1: 'foo', 2: None}}
d2 = {'a': {1: None, 2: 'bar'}}
d3 = {'b': {3: 'baz'}}
d4 = {'a': {1: 'quux'}}
from collections import MutableMapping
def rec_merge(d1, d2):
'''
Update two dicts of dicts recursively,
if either mapping has leaves that are non-dicts,
the second's leaf overwrites the first's.
'''
for k, v in d1.items(): # in Python 2, use .iteritems()!
if k in d2:
# this next check is the only difference!
if all(isinstance(e, MutableMapping) for e in (v, d2[k])):
d2[k] = rec_merge(v, d2[k])
# we could further check types and merge as appropriate here.
d3 = d1.copy()
d3.update(d2)
return d3
そして今
from functools import reduce
reduce(rec_merge, (d1, d2, d3, d4))
戻り値
{'a': {1: 'quux', 2: 'bar'}, 'b': {3: 'baz'}}
元の質問への適用:
これを合法的なPython(Python 2.7以降ではリテラルに設定される)にするために、文字の周りの中括弧を削除し、それらを一重引用符で囲む必要があります。
dict1 = {1:{"a":'A'}, 2:{"b":'B'}}
dict2 = {2:{"c":'C'}, 3:{"d":'D'}}
そしてrec_merge(dict1, dict2)
今返す:
{1: {'a': 'A'}, 2: {'c': 'C', 'b': 'B'}, 3: {'d': 'D'}}
これは、元の質問の望ましい結果と一致します(たとえば、{A}
をに変更した後など'A'
)。
y
まで平坦化したいc
ですか、それとも何ですか?あなたの例は不完全です。