2

我有两个非常复杂的字典对象,它们是通过将大型 xml 文件转换为 python 字典来创建的。

我不知道字典的深度,只想比较并想要以下输出......

例如我的字典是这样的

d1 = {"great grand father":
         {"name":"John",
          "grand father":
             {"name":"Tom",
              "father":
                 {"name":"Andy",
                  "Me":
                     {"name":"Mike",
                      "son": 
                         {"name":"Tom"}
                     }
                 }
             }
         }
     }

d2 也是类似的,但可能任何一个字段丢失或更改如下

d2 = {"great grand father":
         {"name":"John",
          "grand father":
             {"name":"Tom",
              "father":
                 {"name":"Andy",
                  "Me":
                     {"name":"Tonny",
                      "son": 
                         {"name":"Tom"}
                     }
                 }
             }
         }
     }

字典比较应该给我这样的结果 -

Expected Key/Val : Me->name/"Mike" 
Actual Key/Val : Me->name/"Tonny"

如果 d2 中的“Me”中不存在键“name”,它应该给我以下输出

Expected Key/Val : Me->name/"Mike" 
Actual Key/Val : Me->name/NOT_FOUND

我重复字典深度可以是可变的或动态生成的。这里给出的两个词典作为例子......

我在SO中看到的所有字典比较问题及其答案都是相关的固定深度字典......

4

2 回答 2

2

你很幸运,这是我工作的项目的一部分。

您需要一个递归函数,例如:

def checkDifferences(dict_a,dict_b,differences=[])

您可以首先检查一个或另一个中不存在的键。例如

Expected Name/Tom Actual None

然后比较值的类型,即检查值是字典还是列表等。

如果是,那么您可以使用 dict_a/b 的值递归调用该函数。递归调用时传递差异数组。

如果值的类型是列表并且列表中可能包含字典,那么您需要将列表转换为字典并在转换后的字典上调用函数。

很抱歉,我无法提供更多帮助,但我无法再访问源代码。希望这足以让您入门。

于 2013-06-27T12:50:29.380 回答
1

在这里,我找到了一种比较任何两个字典的方法-

我尝试过各种深度的字典并为我工作。代码不是那么模块化,仅供参考 -

import pprint

pp = pprint.PrettyPrinter(indent=4)

dict1 = { 'Person' : { 'Male' : {'Boys' : {'Roger' : {'age' : 20},
                                           'Rafa' : {'age' : 25}
                                          }
                                },
                       'Female' : { 'Girls' : {'Serena' : {'age' : 23},
                                               'Maria' : {'age' : 15}
                                              }
                                  }

                     },
          'Animal' : { 'Huge' : {'Elephant' : {'color' : 'black' }
                                }
                     }
        }
'''
dict2 = { 'Person' : { 'Male' : {'Boys' : {'Roger' : {'age' : 20}
                                          }
                                },
                       'Female' : { 'Girls' : {'Serena' : {'age' : 23},
                                               'Maria' : {'age' : 1}
                                              }
                                  }
                     }
        }

dict2 = { 'Person' : { 'Male' : {'Boys' : {'Roger' : {'age' : 20},
                                           'Rafa' : {'age' : 2}
                                          }
                                }
                     }
        }
'''

dict2 = { 'Person' : { 'Male' : {'Boys' : {'Roger' : {'age' : 2}}},
                       'Female' : 'Serena'}
        }


key_list = []
err_list = {}
def comp(exp,act):
    for key in exp:
        key_list.append(key)
        exp_val = exp[key]
        try:
            act_val = act[key]
            is_dict_exp = isinstance(exp_val,__builtins__.dict)
            is_dict_act = isinstance(act_val,__builtins__.dict)

            if is_dict_exp == is_dict_act == True:
                comp(exp_val,act_val)
            elif is_dict_exp == is_dict_act == False:
                if not exp_val == act_val:
                    temp = {"Exp" : exp_val,"Act" : act_val}
                    err_key = "-->".join(key_list)
                    if err_list.has_key(key):
                        err_list[err_key].update(temp)
                    else:
                        err_list.update({err_key : temp})
            else:
                temp = {"Exp" : exp_val, "Act" : act_val}
                err_key = "-->".join(key_list)
                if err_list.has_key(key):
                    err_list[err_key].update(temp)
                else:
                    err_list.update({err_key : temp})

        except KeyError:
            temp = {"Exp" : exp_val,"Act" : "NOT_FOUND"}
            err_key = "-->".join(key_list)
            if err_list.has_key(key):
                err_list[err_key].update(temp)
            else:
                err_list.update({err_key : temp})
        key_list.pop()

comp(dict1,dict2)

pp.pprint(err_list)

这是我的代码的输出 -

{   'Animal': {   'Act': 'NOT_FOUND',
                  'Exp': {   'Huge': {   'Elephant': {   'color': 'black'}}}},
    'Person-->Female': {   'Act': 'Serena',
                           'Exp': {   'Girls': {   'Maria': {   'age': 15},
                                                   'Serena': {   'age': 23}}}},
    'Person-->Male-->Boys-->Rafa': {   'Act': 'NOT_FOUND', 'Exp': {   'age': 25}},
    'Person-->Male-->Boys-->Roger-->age': {   'Act': 2, 'Exp': 20}
}

也可以尝试使用注释代码中给出的其他字典..

还有一件事 - 在预期字典中检查键并与实际匹配。如果我们以交替顺序传递字典,其他方式匹配也是可能的......

comp(dict2,dict1)
于 2013-07-03T14:13:34.613 回答