【问题标题】:Comparing python dictionaries and find diffrence of the two比较python字典并找出两者的差异
【发布时间】:2014-01-23 00:32:41
【问题描述】:

所以我试图编写一个 python 程序,它需要 2 个 .json 文件比较内容并显示两者之间的差异。到目前为止,我的程序需要用户输入来选择两个文件并比较这两个文件就好了。我在试图弄清楚如何打印两个文件之间的实际差异时遇到了困难。

我的程序:

#!/usr/bin/env python2

import json

#get_json() requests user input to select a .json file
#and creates a python dict with the information
def get_json():
    file_name = raw_input("Enter name of JSON File: ")
    with open(file_name) as json_file:
        json_data = json.load(json_file)
        return json_data

#compare_json(x,y) takes 2 dicts, and compairs the contents
#print match if equal, or not a match if there is difrences
def compare_json(x,y):
    for x_values, y_values in zip(x.iteritems(), y.iteritems()):
        if x_values == y_values:
            print 'Match'
        else:
            print 'Not a match'

def main():
    json1 = get_json()
    json2 = get_json()
    compare_json(json1, json2)

if __name__ == "__main__":
    main()

我的 .json 示例:

{
    "menu": {
        "popup": {
            "menuitem": [
                {
                    "onclick": "CreateNewDoc()",
                    "value": "New"
                },
                {
                    "onclick": "OpenDoc()",
                    "value": "Open"
                },
                {
                    "onclick": "CloseDoc()",
                    "value": "Close"
                }
            ]
        },
        "id": "file",
        "value": "File"
    }
}

【问题讨论】:

  • 你想只在顶层比较还是递归比较?
  • 或者如果不清楚,您可以编辑您的问题以添加要比较的第二个 json 示例吗?
  • .. 和预期的结果,请:)
  • 看来你应该使用 Python sets :)
  • 我想递归比较。在这两个文件中,我想将第一个文件用作“主文件”并将第二个文件与主文件进行比较。第二个具有我不想打印的主人的任何值或键。

标签: python json dictionary


【解决方案1】:

您的问题源于字典存储在具有内部逻辑一致性的结构中 - 当您要求 someDict.items()someOtherDict.items() 时,元素的键值对是通过相同的算法计算的。但是,由于任一字典中可能存在的键不同,调用dict.items() 返回的任一列表中的相应索引中可能不存在相同的键。因此,您最好检查另一个字典中是否存在特定键,并比较两者中的关联值。

def compare_json(x,y):
    for x_key in x:
        if x_key in y and x[x_key] == y[x_key]:
            print 'Match'
        else:
            print 'Not a match'
    if any(k not in x for k in y):
        print 'Not a match'

如果要打印出实际差异:

def printDiffs(x,y):
    diff = False
    for x_key in x:
        if x_key not in y:
            diff = True
            print "key %s in x, but not in y" %x_key
        elif x[x_key] != y[x_key]:
            diff = True
            print "key %s in x and in y, but values differ (%s in x and %s in y)" %(x_key, x[x_key], y[x_key])
    if not diff:
        print "both files are identical"

【讨论】:

  • 谢谢,帮助很大。我认为我的问题措辞不好。我想找出这两个字典的不同之处并打印出这些不同之处。
  • 我了解如何检查文件是否相似,但我坚持尝试打印值/键的实际差异?
  • 再次感谢 G4dget 的所有帮助。所以我尽我所能跟随你的代码。在 elif 中,如果键同时在第一个文件和第二个文件中,但具有不同的值,它会打印哪个键,然后使用 (x[x_key] 用于第一个和 y[x_key]第二个)。 x[x_key] 和 y[x_key] 都返回整个键,如何修改它们以仅显示键中不同的值?我一直在尝试我自己的变体,但只有错误。
  • elif 中的代码应该只打印出同一键不同的xy 的值。例如,如果键是"menu",并且该键的值在xy 之间不同,那么这两个值都会与键一起打印出来。修改我的代码以不打印密钥本身的最简单方法是删除print 中的第一个%s 并从%(x_key, x[x_key], y[x_key]) 中删除x_key
  • 由于某种原因,elif 中的代码正在打印除键名之外的所有内容。例如在上面的 .json 中,如果我在第二个文件中将“Value”:“New”更改为“Value”:“Old”。 elif 将打印除键菜单之外的 x 和 y 中的所有内容。
【解决方案2】:

您可能想在 python 中试用 jsondiff 库。 https://pypi.python.org/pypi/jsondiff/0.1.0

从该站点引用的示例如下。

>>> from jsondiff import diff

>>> diff({'a': 1}, {'a': 1, 'b': 2})
{<insert>: {'b': 2}}

>>> diff({'a': 1, 'b': 3}, {'a': 1, 'b': 2})
{<update>: {'b': 2}}

>>> diff({'a': 1, 'b': 3}, {'a': 1})
{<delete>: ['b']}

>>> diff(['a', 'b', 'c'], ['a', 'b', 'c', 'd'])
{<insert>: [(3, 'd')]}

>>> diff(['a', 'b', 'c'], ['a', 'c'])
{<delete>: [1]}

# Similar items get patched
>>> diff(['a', {'x': 3}, 'c'], ['a', {'x': 3, 'y': 4}, 'c'])
{<update>: [(1, {<insert>: {'y': 4}})]}

# Special handling of sets
>>> diff({'a', 'b', 'c'}, {'a', 'c', 'd'})
{<add>: set(['d']), <discard>: set(['b'])}

# Parse and dump JSON
>>> print diff('["a", "b", "c"]', '["a", "c", "d"]', parse=True, dump=True, indent=2)
{
  "$delete": [
    1
  ],
  "$insert": [
    [
      2,
      "d"
    ]
  ]
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-03
    • 1970-01-01
    • 1970-01-01
    • 2017-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多