【问题标题】:python nested dictionary comparison [duplicate]python嵌套字典比较[重复]
【发布时间】:2018-09-19 05:10:28
【问题描述】:

我在与列表中的嵌套字典进行比较时遇到问题,我试图仅显示值更改的键的数据,以及它们之间的差异。我已经尝试过了(示例已简化,我的比较数据中可以有不同级别的嵌套):

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

但是,当我运行它时,我仍然看到相同的键:

[{'poker': {'John': {'Wins': 6, 'Losses': 1}, 'Jack': {'Wins': 6, “损失”:5},“比尔”:{“赢”:3,“损失”:0}}},{“二十一点”: {'Bill': {'Wins': 4, 'Losses': 3}, 'John': {'Wins': 7, 'Losses': 0}, “杰克”:{“胜利”:1,“失败”:3}}}]

以及我期望看到的:

[{"poker":{"John":{"Wins": 6}, "Jack": {"Losses": 5}, "Bill": {"Wins": 3,“损失”:0}}},{“二十一点”:{“杰克”:{“胜利”:1,“损失”:3}}}]

如果我能看到新旧之间的数量差异,那就太好了,但我只想只显示发生了什么变化。

【问题讨论】:

    标签: python dictionary nested comparison


    【解决方案1】:

    我认为您的代码中只是一个小错误,如果您修复它,一切都会按您预期的那样工作

    线

    type(new(key)) == dict
    

    总是失败,因为您应该使用 new[key] 访问字典的元素。如果在内部尝试,您可以替换该行

    if isinstance(new[key], dict)
    

    顺便说一句,让try except保持这种沉默从来都不是一个好主意。

    【讨论】:

    • 任何在 SO 上发布 Python 代码的人都应该受到 -50 代表的惩罚,其中包括一个裸例外。
    • 不幸的是,在 Python 2.x 中,第三方代码可能会引发不继承自 Exception 的异常,因此在 Python 2.x 中,在某些情况下您可能不得不使用裸除了。 @ekhumoro
    • 这正是我想要的,谢谢!请原谅我的菜鸟自学代码。
    • @TylerCowan。我认为您错过了发布问题(如当前问题)没有任何借口的观点,这些问题可以通过简单地阅读回溯来轻松解决。当然,如果没有回溯,那完全是一个不同的问题(显然与此无关)。
    • 显然我错过了我使用 ('s 而不是 ['s. if type(new[key]) == dict: 也可以。感谢您的帮助!我会确保让沉默在另一个之前失败。
    【解决方案2】:

    您可以对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}}}}]
    

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

    【讨论】:

    • 虽然它确实添加了我想要的比较,但它还包括相同的数据,并且对于我的嵌套结构,我每次需要比较大约 33k 行数据......所以这就是我想消除完全匹配的原因。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-18
    • 1970-01-01
    • 1970-01-01
    • 2022-11-22
    • 2019-07-07
    • 1970-01-01
    相关资源
    最近更新 更多