我有两个具有以下结构的词典:
a = {'joe': [24,32,422], 'bob': [1,42,32,24], 'jack':[0,3,222]}
b = {'joe': [24], 'bob': [1,42,32]}
我想检索这两个词典之间的区别,在这种情况下会产生:
{'joe': [32,422], 'bob': [24], 'jack':[0,3,222]}
我知道我可以用一个凌乱的循环来做到这一点,但我想知道如何以干净,pythonic的方式实现这一目标?
我确实尝试过:a.items() - b.items()
但是我收到以下错误:unsupported operand type(s) for -: 'dict_values' and 'dict_values'
感谢您的帮助
答案 0 :(得分:12)
假设您的任何列表中都没有重复的条目,您可以使用set
而不是列表执行所需的操作:
>>> a = {'joe': [24,32,422], 'bob': [1,42,32,24], 'jack':[0,3,222]}
>>> b = {'joe': [24], 'bob': [1,42,32]}
>>> {key: list(set(a[key])- set(b.get(key,[]))) for key in a}
{'joe': [32, 422], 'bob': [24], 'jack': [0, 3, 222]}
注意两件事:
b.get
而不是b[key]
来处理b
中的密钥是否存在,但a
编辑 - 使用for循环:
我意识到理解可能不是那么自我解释所以这是使用for循环的等效代码:
>>> c = {}
>>> for key in a:
c[key] = list(set(a[key]) - set(b.get(key,[])))
>>> c
{'joe': [32, 422], 'bob': [24], 'jack': [0, 3, 222]}
编辑 - 输掉第二组:
正如Padraic Cunningham在评论中提到的那样(他经常这样做,祝福他的灵魂),你可以利用set.difference
来避免明确地将你的第二个名单投射到一套:
>>> c = {}
>>> for key in a:
c[key] = list(set(a[key]).difference(b.get(key,[])))
>>> c
{'joe': [32, 422], 'bob': [24], 'jack': [0, 3, 222]}
或列表理解:
>>> {key: list(set(a[key]).difference(b.get(key,[]))) for key in a}
{'joe': [32, 422], 'bob': [24], 'jack': [0, 3, 222]}
或者如果您想将set.difference
视为类方法而不是实例方法:
>>> {key: list(set.difference(set(a[key]),b.get(key,[]))) for key in a}
{'joe': [32, 422], 'bob': [24], 'jack': [0, 3, 222]}
虽然我觉得这有点笨重但我不太喜欢它。
答案 1 :(得分:7)
您需要使用套装:
diff = {}
for key in a:
diff[key] = list(set(a[key]) - set(b.get(key, [])))
print diff
答案 2 :(得分:3)
另一种方法是使用内置方法filter
:
>>> a = {'joe': [24,32,422], 'bob': [1,42,32,24], 'jack':[0,3,222]}
>>> b = {'joe': [24], 'bob': [1,42,32]}
>>> {key:filter(lambda s: s not in b.get(key,[]), a[key]) for key in a}
{'bob': [24], 'joe': [32, 422], 'jack': [0, 3, 222]}
根据Padraic Cunningham
评论:
在Python 3中,filter
会返回generator
,因此,您需要将其转换为列表,这样:
{key:list(filter(lambda s: s not in b.get(key,[]), a[key])) for key in a}