python嵌套字典比较

时间:2018-04-09 18:08:57

标签: python dictionary nested comparison

我在列表中对嵌套字典进行比较时遇到了麻烦,我试图只显示值变化的键的数据,以及它们之间的差异。我试过这个(示例是简化的,我的比较数据中可以有不同级别的嵌套):

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}}}]

如果我能看到新旧之间的数字差异会很好,但我只会满足于只显示变化的内容。

2 个答案:

答案 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}}}}]

结果为结构添加了一个额外的字典:原始结果和更新数据之间的比较。