TL;博士食谱:{k:d1.get(k, k in d1 or d2[k]) for k in set(d1) | set(d2)}
and |
可以用任何其他集合运算符替换。
根据@torek的评论,另一个可能更容易记住的食谱(虽然完全通用)是:{k:d1.get(k,d2.get(k)) for k in set(d1) | set(d2)}
.
完整答案如下:
我的第一个答案没有正确处理评估为 False 的值。这是处理 Falsey 值的改进版本:
>>> d1 = {'one':1, 'both':3, 'falsey_one':False, 'falsey_both':None}
>>> d2 = {'two':2, 'both':30, 'falsey_two':None, 'falsey_both':False}
>>>
>>> print "d1 - d2:", {k:d1[k] for k in d1 if k not in d2} # 0
d1 - d2: {'falsey_one': False, 'one': 1}
>>> print "d2 - d1:", {k:d2[k] for k in d2 if k not in d1} # 1
d2 - d1: {'falsey_two': None, 'two': 2}
>>> print "intersection:", {k:d1[k] for k in d1 if k in d2} # 2
intersection: {'both': 3, 'falsey_both': None}
>>> print "union:", {k:d1.get(k, k in d1 or d2[k]) for k in set(d1) | set(d2)} # 3
union: {'falsey_one': False, 'falsey_both': None, 'both': 3, 'two': 2, 'one': 1, 'falsey_two': None}
版本为union
是最通用的,可以变成一个函数:
>>> def dict_ops(d1, d2, setop):
... """Apply set operation `setop` to dictionaries d1 and d2
...
... Note: In cases where values are present in both d1 and d2, the value from
... d1 will be used.
... """
... return {k:d1.get(k,k in d1 or d2[k]) for k in setop(set(d1), set(d2))}
...
>>> print "d1 - d2:", dict_ops(d1, d2, lambda x,y: x-y)
d1 - d2: {'falsey_one': False, 'one': 1}
>>> print "d2 - d1:", dict_ops(d1, d2, lambda x,y: y-x)
d2 - d1: {'falsey_two': None, 'two': 2}
>>> import operator as op
>>> print "intersection:", dict_ops(d1, d2, op.and_)
intersection: {'both': 3, 'falsey_both': None}
>>> print "union:", dict_ops(d1, d2, op.or_)
union: {'falsey_one': False, 'falsey_both': None, 'both': 3, 'two': 2, 'one': 1, 'falsey_two': None}
如果项目同时存在于两个词典中,则来自的值d1
将会被使用。当然我们可以返回值d2
相反,通过更改函数参数的顺序。
>>> print "union:", dict_ops(d2, d1, op.or_)
union: {'both': 30, 'falsey_two': None, 'falsey_one': False, 'two': 2, 'one': 1, 'falsey_both': False}