kew*_*iev 2 python diff json compare unordered
请链接我回答如果已经回答,我的问题是我想获得多级json的差异,这是无序的.
x=json.loads('''[{"y":2,"x":1},{"x":3,"y":4}]''')
y=json.loads('''[{"x":1,"y":2},{"x":3,"y":4}]''')
z=json.loads('''[{"x":3,"y":4},{"x":1,"y":2}]''')
import json_tools as jt
import json_delta as jd
print jt.diff(y,z)
print jd.diff(y,z)
print y==z
print x==y
Run Code Online (Sandbox Code Playgroud)
输出是
[{'prev': 2, 'value': 4, 'replace': u'/0/y'}, {'prev': 1, 'value': 3, 'replace': u'/0/x'}, {'prev': 4, 'value': 2, 'replace': u'/1/y'}, {'prev': 3, 'value': 1, 'replace': u'/1/x'}]
[[[2], {u'y': 2, u'x': 1}], [[0]]]
False
True
Run Code Online (Sandbox Code Playgroud)
我的问题是如何让y和z相等,或者如果存在实际差异,则取决于JSON的非顺序.
一种无序的词典列表,但我正在寻找一些水平证明的东西,列表/词典的列表/词典......
Jen*_*ish 12
看看这个python库jsondiff,它将帮助你识别差异
import json
import jsondiff
json1 = json.loads(
'{"isDynamic": false, "name": "", "value": "SID:<sid>", "description": "instance","argsOrder": 1,"isMultiSelect": false}')
json2 = json.loads(
'{ "name": "", "value": "SID:<sid>","isDynamic": false, "description": "instance","argsOrder": 1,"isMultiSelect": false}')
res = jsondiff.diff(json1, json2)
if res:
print("Diff found")
else:
print("Same")
Run Code Online (Sandbox Code Playgroud)
更新:请参阅https://eggachecat.github.io/jycm-json-diff-viewer/进行现场演示!现在它有一个 JS 原生实现。
\n隶属关系:我是该库的作者。
\n是的!您可以使用jycm对其进行比较, jycm具有开箱即用的渲染工具。
\n它使用 LCS、编辑距离和 Kuhn\xe2\x80\x93Munkres 来比较数组。
\n这是一个通用示例,其中集合中的集合和某些集合中的值更改
\nfrom jycm.helper import make_ignore_order_func\nfrom jycm.jycm import YouchamaJsonDiffer\n\nleft = {\n "set_in_set": [\n {\n "id": 1,\n "label": "label:1",\n "set": [\n 1,\n 5,\n 3\n ]\n },\n {\n "id": 2,\n "label": "label:2",\n "set": [\n 4,\n 5,\n 6\n ]\n }\n ]\n}\n\nright = {\n "set_in_set": [\n {\n "id": 2,\n "label": "label:2",\n "set": [\n 6,\n 5,\n 4\n ]\n },\n {\n "id": 1,\n "label": "label:1111",\n "set": [\n 3,\n 2,\n 1\n ]\n }\n ]\n}\n\nycm = YouchamaJsonDiffer(left, right, ignore_order_func=make_ignore_order_func([\n "^set_in_set$",\n "^set_in_set->\\\\[\\\\d+\\\\]->set$"\n]))\n\nycm.diff()\n\nexpected = {\n \'list:add\': [\n {\'left\': \'__NON_EXIST__\', \'right\': 2, \'left_path\': \'\', \'right_path\': \'set_in_set->[1]->set->[1]\'}\n ],\n \'list:remove\': [\n {\'left\': 5, \'right\': \'__NON_EXIST__\', \'left_path\': \'set_in_set->[0]->set->[1]\', \'right_path\': \'\'}\n ],\n \'value_changes\': [\n {\'left\': \'label:1\', \'right\': \'label:1111\', \'left_path\': \'set_in_set->[0]->label\',\n \'right_path\': \'set_in_set->[1]->label\', \'old\': \'label:1\', \'new\': \'label:1111\'}\n ]\n}\n\nassert ycm.to_dict(no_pairs=True) == expected\nRun Code Online (Sandbox Code Playgroud)\n您可以设置no_pairs=False来获取所有对。这是一个渲染的示例:
\n\n至于这里的示例,您可以将其用作:
\nfrom jycm.helper import make_ignore_order_func\nfrom jycm.jycm import YouchamaJsonDiffer\n\nleft = {\n "data": [{"x": 1, "y": 2}, {"x": 3, "y": 4}]\n}\n\nright = {\n "data": [{"x": 3, "y": 4}, {"x": 1, "y": 2}]\n}\n\nycm = YouchamaJsonDiffer(left, right, ignore_order_func=make_ignore_order_func([\n "^data",\n]))\n\nycm.diff()\n\nassert ycm.to_dict(no_pairs=True) == {}\nRun Code Online (Sandbox Code Playgroud)\n另外,您的值会被中断为平面上的坐标,您甚至可以定义一个运算符来\n确定两个点是否应该匹配!(然后比较它们的值)
\n这是代码:
\nfrom typing import Tuple\n\nfrom jycm.helper import make_ignore_order_func\nfrom jycm.jycm import YouchamaJsonDiffer\nfrom jycm.operator import BaseOperator\nimport math\n\nleft = {\n "data": [\n {"x": 1, "y": 1},\n {"x": 10, "y": 10},\n {"x": 100, "y": 100}\n ]\n}\n\nright = {\n "data": [\n {"x": 150, "y": 150},\n {"x": 10, "y": 11},\n {"x": 2, "y": 3}\n ]\n}\n\n\nclass L2DistanceOperator(BaseOperator):\n __operator_name__ = "operator:l2distance"\n __event__ = "operator:l2distance"\n\n def __init__(self, path_regex, distance_threshold):\n super().__init__(path_regex=path_regex)\n self.distance_threshold = distance_threshold\n\n def diff(self, level: \'TreeLevel\', instance, drill: bool) -> Tuple[bool, float]:\n distance = math.sqrt(\n (level.left["x"] - level.right["x"]) ** 2 + (level.left["y"] - level.right["y"]) ** 2\n )\n info = {\n "distance": distance,\n "distance_threshold": self.distance_threshold,\n "pass": distance < self.distance_threshold\n }\n\n if not drill:\n instance.report(self.__event__, level, info)\n return False, 1 if info["pass"] else 0\n return True, 1 if info["pass"] else 0\n\n\nycm = YouchamaJsonDiffer(left, right, ignore_order_func=make_ignore_order_func([\n "^data$",\n]), custom_operators=[\n L2DistanceOperator("^data->\\\\[.*\\\\]$", 10),\n])\n\nycm.diff()\n\nexpected = {\n \'just4vis:pairs\': [\n {\'left\': 1, \'right\': 2, \'left_path\': \'data->[0]->x\', \'right_path\': \'data->[2]->x\'},\n {\'left\': {\'x\': 1, \'y\': 1}, \'right\': {\'x\': 2, \'y\': 3}, \'left_path\': \'data->[0]\',\n \'right_path\': \'data->[2]\'},\n {\'left\': 1, \'right\': 3, \'left_path\': \'data->[0]->y\', \'right_path\': \'data->[2]->y\'},\n {\'left\': {\'x\': 1, \'y\': 1}, \'right\': {\'x\': 2, \'y\': 3}, \'left_path\': \'data->[0]\',\n \'right_path\': \'data->[2]\'},\n {\'left\': {\'x\': 1, \'y\': 1}, \'right\': {\'x\': 2, \'y\': 3}, \'left_path\': \'data->[0]\',\n \'right_path\': \'data->[2]\'}\n ],\n \'list:add\': [\n {\'left\': \'__NON_EXIST__\', \'right\': {\'x\': 150, \'y\': 150}, \'left_path\': \'\', \'right_path\': \'data->[0]\'}\n ],\n \'list:remove\': [\n {\'left\': {\'x\': 100, \'y\': 100}, \'right\': \'__NON_EXIST__\', \'left_path\': \'data->[2]\', \'right_path\': \'\'}\n ],\n \'operator:l2distance\': [\n {\'left\': {\'x\': 1, \'y\': 1}, \'right\': {\'x\': 2, \'y\': 3}, \'left_path\': \'data->[0]\',\n \'right_path\': \'data->[2]\', \'distance\': 2.23606797749979, \'distance_threshold\': 10,\n \'pass\': True},\n {\'left\': {\'x\': 10, \'y\': 10}, \'right\': {\'x\': 10, \'y\': 11}, \'left_path\': \'data->[1]\',\n \'right_path\': \'data->[1]\', \'distance\': 1.0, \'distance_threshold\': 10,\n \'pass\': True}\n ],\n \'value_changes\': [\n {\'left\': 1, \'right\': 2, \'left_path\': \'data->[0]->x\', \'right_path\': \'data->[2]->x\', \'old\': 1, \'new\': 2},\n {\'left\': 1, \'right\': 3, \'left_path\': \'data->[0]->y\', \'right_path\': \'data->[2]->y\', \'old\': 1, \'new\': 3},\n {\'left\': 10, \'right\': 11, \'left_path\': \'data->[1]->y\', \'right_path\': \'data->[1]->y\', \'old\': 10, \'new\': 11}\n ]\n}\nassert ycm.to_dict() == expected\nRun Code Online (Sandbox Code Playgroud)\n正如您所看到的,jycm 报告了点的添加和删除{\'x\': 150, \'y\': 150}以及{\'x\': 100, \'y\': 100}它们\n距离太远(超过 10)以及其他两个点的值更改。
PS 渲染器演示
\n
kew*_*iev -5
用以下函数部分解决了这个问题
def diff(prev,lat):
p=prev
l=lat
prevDiff = []
latDiff = []
for d1 in p[:]:
flag = False
for d2 in l:
if len(set(d1.items()) ^ set(d2.items())) == 0:
p.remove(d1)
l.remove(d2)
flag = True
break
if not flag:
prevDiff.append(d1)
p.remove(d1)
prevDiff = prevDiff + p
latDiff = latDiff + l
resJSONdata=[]
if len(prevDiff) != 0:
resJSONdata.append({'prevCount':len(prevDiff)})
resJSONdata.append({'prev':prevDiff})
if len(latDiff) != 0:
resJSONdata.append({'latestCount':len(latDiff)})
resJSONdata.append({'latest':latDiff})
# return json.dumps(resJSONdata,indent = 4,sort_keys=True)
return resJSONdata
Run Code Online (Sandbox Code Playgroud)
它不是递归地进入级别,但出于我的目的,这解决了问题