【问题标题】:How to get/print the differences between two dictionaries?如何获取/打印两个字典之间的差异?
【发布时间】:2021-05-28 05:48:31
【问题描述】:

我有两个函数必须返回相同的字典(一个是旧方法,另一个是替换旧方法的新方法)。当我测试新函数给我的结果与旧函数相同时。我正在尝试创建一个程序,该程序将两个字典作为输入,并验证它们是否具有相同的信息并告诉我它们之间的任何差异。我的范围是了解新功能的哪些信息是错误的。

这两个字典每次都可以更改。它们可能具有仅包含字符串或字典或字典列表的键。此外,这些字典列表可能包含具有字符串值的键或字典或另一个字典列表。字典可以任意复杂。

我试过这个,但结果并不好。 attr_prod 是返回旧函数的字典示例。 attr_test 是返回新函数的字典示例。

def main():
    attr_prod = {
            'key1': 'a',
            'key2': [ {
                        'key3': 'n1',
                        'key4': 'n2',
                        'key5': [ {
                                    'key6': 'n1',
                                    'key7': 'n2',
                                    'key8': {
                                        'key10': 'g1',
                                        'key11': 'g2',
                                        'key12': 'g3'
                                        }
                                    },
                                    {
                                    'key6': 'n5',
                                    'key7': 'n6',
                                    'key8': {
                                        'key10': 'g4',
                                        'key11': 'g5',
                                        'key12': 'g6'
                                    }
                                 }
                                ]
                        }
                    ],
            'key20': {
                        'key21': 'g4',
                        'key22': 'g5',
                        'key23': 'g6'
                    }
        }

    attr_test = {
            'key1': 'a',
            'key2': [ {
                        'key3': 'different info',
                        'key4': 'n2',
                        'key5': [   {
                                    'key6': 'n1',
                                    'key7': 'n2',
                                    'key8': {
                                        'key10': 'g1',
                                        'key11': 'g2',
                                        'key12': 'g3'
                                        }
                                    },
                                    {
                                    'key6': 'n5',
                                    'key7': 'n6',
                                    'key8': {
                                        'key10': 'different info',
                                        'key11': 'g5',
                                        'key12': 'g6'
                                        }
                                    },
                                    {
                                    'key6': 'this is new',
                                    'key7': 'this is new',
                                    'key8': {
                                        'key10': 'new',
                                        'key11': 'new',
                                        'key12': 'new'
                                    }
                                }
                            ]
                        }
                    ],
            'key20': {
                        'key21': 'g4',
                        'key22': 'different info',
                        'key23': 'g6'
                    }
        }

    for key, value_prod in attr_prod.items():
            if isinstance(value_prod, basestring):
                check(key, value_prod, attr_test[key])
            elif isinstance(value_prod, list):
                n_rec = 0
                for rec in value_prod:
#                   if isinstance(rec, basestring):
#                       check(key, rec, attr_test[key][n_rec])
                    print rec
                    if isinstance(rec, dict):
                        for key2, value_prod2 in rec.items():
                            if isinstance(value_prod2, basestring):
                                check(key, value_prod2, attr_test[key][n_rec][key2])
                            elif isinstance(value_prod2, list):
                                n_rec2 = 0
                                for rec2 in value_prod2:
                                    for key3, value_prod3 in rec2.items():
                                        if isinstance(value_prod3, basestring):
                                            check(key, value_prod3, attr_test[key][n_rec][key2][n_rec2][key3])
                                n_rec2 += 1
                    n_rec += 1


def check(key, value_prod, value_test):
    if value_test != value_prod:
        print "KO key: %s test: -%s- prod: -%s-" % (key, value_test, value_prod)
    

【问题讨论】:

  • “结果不好”到底是什么意思?
  • 我的意思是我无法理解差异在哪里。它打印了一些键和值,但我无法理解新函数有什么问题或字典中的位置。正确的结果必须是字典 attr_prod(返回旧函数的字典),我需要了解新函数的哪些数据不正确(返回新函数的字典是 attr_test)。
  • dict1 == dict2 就足够了,因为这是一个深度比较。如果条件为假,您可以遍历两个 dicts 以查看有什么不同。但是您必须指定“不同”的含义。例如,两个字典中“key2”的值不同,因此您可以打印这两个列表。或者,如果您深入挖掘,您会发现它们是相同的,除了一个值并仅打印该值。
  • 但我需要深入了解。从某种意义上说,'key3' 有不同的信息,但 key 4 没问题,那么我不想打印 key 4。key10 有不同的信息,然后我想打印 key10 和不同的值。
  • 一种方法可能是跟踪对字典所做的更改,如我的answer 中所示的相关问题。否则,我认为您想做的事情在任何一般意义上都不可行。

标签: python dictionary recursion compare


【解决方案1】:

我建议将递归字典比较函数用作生成器(这样您就可以使用下一个函数有效地检测至少一个差异):

def compareDict(before,after):
    for k,old in before.items():
        if k not in after: yield f"{k}: deleted";continue
        new = after[k]
        if type(old) != type(new):
            yield f"{k}: changed from: {old}"
            yield f"{k}: changed   to: {new}"
        elif isinstance(old,dict):
            yield from (f"{k}:{change}" for change in compareDict(old,new))
        elif isinstance(old,(tuple,list)):
            b = {f"[{i}]":v for i,v in enumerate(old)}
            a = {f"[{i}]":v for i,v in enumerate(new)}
            yield from (f"{k}:{change}" for change in compareDict(b,a))
        elif old != new:
            yield f"{k}: changed from: {old}"
            yield f"{k}: changed   to: {new}"
    for k,new in after.items():
        if k not in before: yield f"{k}: added: {new}"

输出:

for change in compareDict(attr_prod,attr_test): print(change)

key2:[0]:key3: changed from: n1
key2:[0]:key3: changed   to: different info
key2:[0]:key5:[1]:key8:key10: changed from: g4
key2:[0]:key5:[1]:key8:key10: changed   to: different info
key2:[0]:key5:[2]: added: {'key6': 'this is new', 'key7': 'this is new', 'key8': {'key10': 'new', 'key11': 'new', 'key12': 'new'}}
key20:key22: changed from: g5
key20:key22: changed   to: different info

【讨论】:

    猜你喜欢
    • 2013-11-14
    • 1970-01-01
    • 2019-08-03
    • 1970-01-01
    • 2012-02-09
    • 2014-04-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多