如何比较Python中两个字典列表?
我想知道怎么比较两个字典列表。结果应该是从字典列表B中找出那些不同的项。
举个例子:
ldA = [{'user':"nameA", 'a':7.6, 'b':100.0, 'c':45.5, 'd':48.9},
{'user':"nameB", 'a':46.7, 'b':67.3, 'c':0.0, 'd':5.5}]
ldB =[{'user':"nameA", 'a':7.6, 'b':99.9, 'c':45.5, 'd':43.7},
{'user':"nameB", 'a':67.7, 'b':67.3, 'c':1.1, 'd':5.5},
{'user':"nameC", 'a':89.9, 'b':77.3, 'c':2.2, 'd':6.5}]
在这里,我想比较ldA和ldB。它应该输出下面的结果。
ldB -> {user:"nameA", b:99.9, d:43.7}
ldB -> {user:"nameB", a:67.7, c:1.1 }
ldb -> {user:"nameC", a:89.9, b:77.3, c:2.2, d:6.5}
我看过下面的链接,但那里只返回了名字,而我想要的是名字和对应的值,就像上面那样。
6 个回答
1
我假设这两个列表里的dict
是按相同的顺序排列的。
在这个假设下,你可以使用下面的代码:
def diffs(L1, L2):
answer = []
for i, d1 in enumerate(L1):
d = {}
d2 = L2[i]
for key in d1:
if key not in d1:
print key, "is in d1 but not in d2"
elif d1[key] != d2[key]:
d[key] = d2[key]
answer.append(d)
return answer
这段代码还没有测试过。如果有错误,请留言告诉我,我会修正的。
3
我的方法是:先建立一个查找表,里面包含要排除的值,然后再从每个列表中找出合适的值进行排除,得到最终的结果。
lookup = dict((x['user'], dict(x)) for x in ldA)
# 'dict(x)' is used here to make a copy
for v in lookup.values(): del v['user']
result = [
dict(
(k, v)
for (k, v) in item.items()
if item['user'] not in lookup or lookup[item['user']].get(k, v) == v
)
for item in ldB
]
7
对于一个通用的解决方案,可以考虑以下内容。即使用户在列表中的顺序不一致,它也能正确地进行差异比较。
def dict_diff ( merge, lhs, rhs ):
"""Generic dictionary difference."""
diff = {}
for key in lhs.keys():
# auto-merge for missing key on right-hand-side.
if (key not in rhs):
diff[key] = lhs[key]
# on collision, invoke custom merge function.
elif (lhs[key] != rhs[key]):
diff[key] = merge(lhs[key], rhs[key])
for key in rhs.keys():
# auto-merge for missing key on left-hand-side.
if (key not not lhs):
diff[key] = rhs[key]
return diff
def user_diff ( lhs, rhs ):
"""Merge dictionaries using value from right-hand-side on conflict."""
merge = lambda l,r: r
return dict_diff(merge, lhs, rhs)
import copy
def push ( x, k, v ):
"""Returns copy of dict `x` with key `k` set to `v`."""
x = copy.copy(x); x[k] = v; return x
def pop ( x, k ):
"""Returns copy of dict `x` without key `k`."""
x = copy.copy(x); del x[k]; return x
def special_diff ( lhs, rhs, k ):
# transform list of dicts into 2 levels of dicts, 1st level index by k.
lhs = dict([(D[k],pop(D,k)) for D in lhs])
rhs = dict([(D[k],pop(D,k)) for D in rhs])
# diff at the 1st level.
c = dict_diff(user_diff, lhs, rhs)
# transform to back to initial format.
return [push(D,k,K) for (K,D) in c.items()]
接下来,你可以检查这个解决方案:
ldA = [{'user':"nameA", 'a':7.6, 'b':100.0, 'c':45.5, 'd':48.9},
{'user':"nameB", 'a':46.7, 'b':67.3, 'c':0.0, 'd':5.5}]
ldB =[{'user':"nameA", 'a':7.6, 'b':99.9, 'c':45.5, 'd':43.7},
{'user':"nameB", 'a':67.7, 'b':67.3, 'c':1.1, 'd':5.5},
{'user':"nameC", 'a':89.9, 'b':77.3, 'c':2.2, 'd':6.5}]
import pprint
if __name__ == '__main__':
pprint.pprint(special_diff(ldA, ldB, 'user'))