ディクショナリのキー間で集合操作を実行できることは非常に便利ですが、辞書自体で集合操作を実行できればと思うことがよくあります。
2 つの辞書の違いを取るためのレシピをいくつか見つけましたが、それらは非常に冗長であることがわかり、もっと Pythonic な答えが必要だと感じました。
ディクショナリのキー間で集合操作を実行できることは非常に便利ですが、辞書自体で集合操作を実行できればと思うことがよくあります。
2 つの辞書の違いを取るためのレシピをいくつか見つけましたが、それらは非常に冗長であることがわかり、もっと Pythonic な答えが必要だと感じました。
編集: ここのレシピは False 値を正しく処理しません。別の改善された回答を提出しました。
ここに私が思いついたいくつかのレシピがあります:
>>> d1 = {'one':1, 'both':3}
>>> d2 = {'two':2, 'both':30}
>>>
>>> print "d1 only:", {k:d1.get(k) or d2[k] for k in set(d1) - set(d2)} # 0
d1 only: {'one': 1}
>>> print "d2 only:", {k:d1.get(k) or d2[k] for k in set(d2) - set(d1)} # 1
d2 only: {'two': 2}
>>> print "in both:", {k:d1.get(k) or d2[k] for k in set(d1) & set(d2)} # 2
in both: {'both': 3}
>>> print "in either:", {k:d1.get(k) or d2[k] for k in set(d1) | set(d2)} # 3
in either: {'both': 3, 'two': 2, 'one': 1}
#0 と #2 の式はもっと単純にすることもできますが、この式の一般性が気に入っています。これにより、このレシピをどこにでもコピー アンド ペーストし、最後に set 操作を必要なものに変更するだけで済みます。
もちろん、これを関数に変換できます。
>>> def dict_ops(d1, d2, setop):
... return {k:d1.get(k) or d2[k] for k in setop(set(d1), set(d2))}
...
>>> print "d1 only:", dict_ops(d1, d2, lambda x,y: x-y)
d1 only: {'one': 1}
>>> print "d2 only:", dict_ops(d1, d2, lambda x,y: y-x)
d2 only: {'two': 2}
>>> import operator as op
>>> print "in both:", dict_ops(d1, d2, op.and_)
in both: {'both': 3}
>>> print "in either:", dict_ops(d1, d2, op.or_)
in either: {'both': 3, 'two': 2, 'one': 1}
>>> print "in either:", dict_ops(d2, d1, lambda x,y: x|y)
in either: {'both': 30, 'two': 2, 'one': 1}
さらにいくつかの例を次に示します。
セット追加d1 + d2
{key: value for key, value in d1.items() + d2.items()}
# here values that are present in `d1` are replaced by values in `d2`
あるいは、
d3 = d1.copy()
d3.update(d2)
セット差d1 - d2
{key: value for key, value in d1.items() if key not in d2}