我在列表中对嵌套字典进行比较时遇到了麻烦,我试图只显示值变化的键的数据,以及它们之间的差异。我试过这个(示例是简化的,我的比较数据中可以有不同级别的嵌套):
old = [{"poker":{"John":{"Wins": 4, "Losses": 3}, "Jack": {"Wins": 6, "Losses": 1}}},
{"Blackjack":{"Bill": {"Wins": 4, "Losses": 3}, "John": {"Wins": 7, "Losses": 0}}}]
new = [{"poker":{"John":{"Wins": 6, "Losses": 3}, "Jack": {"Wins": 6, "Losses": 5}, "Bill": {"Wins": 3, "Losses": 0}}},
{"Blackjack":{"Bill": {"Wins": 4, "Losses": 3}, "John": {"Wins": 7, "Losses": 0}, "Jack":
{"Wins": 1, "Losses": 3}}}]
def nested_compare(new, old):
for key in new:
try:
if type(new(key)) == dict:
nested_compare(old[key], new[key])
except:
pass
oldkeys = set(old.keys())
newkeys = set(new.keys())
samekeys = newkeys.intersection(oldkeys)
unchanged = set(k for k in samekeys if old[k] == new[k])
for key in list(unchanged):
try:
del new[key]
del old[key]
except KeyError:
pass
return new, old
final = []
x = 0
for entry in new:
new_data, old_data = nested_compare(entry, old[x])
x += 1
final.append(new_data)
print final
然而,当我运行它时,我仍然看到相同的键:
[{'扑克':{'约翰':{'胜利':6,'损失':1},'杰克':{'胜利':6, '损失':5},'比尔':{'胜利':3,'损失':0}}},{'Blackjack': {'比尔':{'胜利':4,'损失':3},'约翰':{'胜利':7,'损失':0}, '杰克':{'胜利':1,'损失':3}}}}
我希望看到的内容:
[{“扑克”:{“John”:{“胜利”:6},“杰克”:{“损失”:5},“比尔”:{“胜利”: 3,“损失”:0}}},{“Blackjack”:{“杰克”:{“胜利”:1,“损失”:3}}}]
如果我能看到新旧之间的数字差异会很好,但我只会满足于只显示变化的内容。
答案 0 :(得分:1)
我认为您的代码中只有一个小错误,如果您修复它,事情会按预期工作
该行
type(new(key)) == dict
总是失败,因为您应该使用new [key]访问字典的元素。如果在里面尝试使用
,你可以替换该行if isinstance(new[key], dict)
顺便说一下,做出这种沉默try except
永远不是一个好主意。
答案 1 :(得分:0)
您可以使用zip
的递归来获取完整的更改列表:
old = [{"poker":{"John":{"Wins": 4, "Losses": 3}, "Jack": {"Wins": 6, "Losses": 1}}}, {"Blackjack":{"Bill": {"Wins": 4, "Losses": 3}, "John": {"Wins": 7, "Losses": 0}}}]
new = [{"poker":{"John":{"Wins": 6, "Losses": 3}, "Jack": {"Wins": 6, "Losses": 5}, "Bill": {"Wins": 3, "Losses": 0}}}, {"Blackjack":{"Bill": {"Wins": 4, "Losses": 3}, "John": {"Wins": 7, "Losses": 0}, "Jack": {"Wins": 1, "Losses": 3}}}]
def compare(player1, player2):
return {a:compare(b, d) if isinstance(b, dict) and isinstance(d, dict) else {'old':min([b, d]), 'new':max([b, d])} for [a, b], [c, d] in zip(player1.items(), player2.items())}
final_data = [compare(p1, p2) for p1, p2 in zip(old, new)]
输出:
[{'poker': {'John': {'Wins': {'new': 6, 'old': 4}, 'Losses': {'new': 3, 'old': 3}}, 'Jack': {'Wins': {'new': 6, 'old': 6}, 'Losses': {'new': 5, 'old': 1}}}}, {'Blackjack': {'Bill': {'Wins': {'new': 4, 'old': 4}, 'Losses': {'new': 3, 'old': 3}}, 'John': {'Wins': {'new': 7, 'old': 7}, 'Losses': {'new': 0, 'old': 0}}}}]
结果为结构添加了一个额外的字典:原始结果和更新数据之间的比较。