赞
踩
最近有个需求要求比较json数据,当然有最简单的方法,循环每个键来比值,但是我偏不!因为正好想趁这个机会写一个文本比较的工具(类似git自带的比较),我搜了一下网络只找到一个LD算法似乎可以用,自己写了个demo效率一般把,而且感觉好复杂太高深。所以还是以我的理解写了一个比较工具。
水平有限所以我不会写很高深的东西,所以尽量往简单的地方靠。基本概念,就是先把文本分段(比如5行一段),然后在这5行里找一个连续最多的行做基准(文本差异度>60的认为是新增行,其他的是编辑行),向下连续查找。简单的说就是尽量把能连续对上的作为基准,一路往下对。
这里提一下,如果希望比对的更精确,可以把findLen设置的大一点,比如设置成left或right里比较大的行数,这样比对起来会避免一些问题,如:当中隔了很多行(>findLen)才是正确的行,导致检索默认5行没找到,就认为是新增行了。当然这样每条比的数量就多了也就慢了自己把握。
- function compare(){
- this.findLen = 5, // 查块大小,如果你希望更准确可以把这个值改大一点比如50行
- this.jsonSort = function (obj) {
- let names = [];
- let newObj = {};
-
- if (Array.isArray(obj)) {
- let list = [];
- for (let i=0;i<obj.length;i++) {
- list.push(this.jsonSort(obj[i]));
- }
- list.sort();
- return list;
- } else {
- for (let o in obj) {
- names.push(o);
- }
- names.sort();
- for (let i=0;i<names.length;i++) {
- let n = names[i];
- if ("function" != typeof obj[n]) {
- if ("object" == typeof obj[n]) {
- if (obj[n]) {
- newObj[n] = this.jsonSort(obj[n]);
- }
- } else {
- newObj[n] = obj[n];
- }
- }
- }
- }
-
- return newObj;
- },
- this.json2Lines = function (obj) {
- let jsonVal = JSON.stringify(obj, null, '\t');
- let lines = [];
- let lineStr = "";
- console.log(jsonVal);
- for (let i=0;i<jsonVal.length; i++) {
- if ('\t' == jsonVal.charAt(i) || '\n' == jsonVal.charAt(i)) {
- let s = lineStr.trim();
- if (s.length > 0) {
- lines.push(lineStr.trim());
- }
- lineStr = "";
- } else {
- lineStr += jsonVal.charAt(i);
- }
- }
-
- lines.push(lineStr);
- return lines;
- },
- this.difference = function (leftStr, rightStr) {
- let count = 0, tmpCount = 0;
- for (let i=0;i<leftStr.length && i < rightStr.length;i++) {
- if (leftStr.charAt(i) == rightStr.charAt(i)) {
- tmpCount++;
- } else {
- count += tmpCount;
- tmpCount = 0;
- }
- }
-
- if (tmpCount > 0) {
- count+=tmpCount;
- }
-
- return count / Math.max(leftStr.length, rightStr.length) * 100;
- },
- this.compareFind = function (index, start, left, right) {
- let val = {
- right: start,
- series: 0,
- find: false
- };
- if (index < left.length && start < right.length) {
- let score = this.difference(left[index], right[start]);
- if (score > 60) {
- let rtn = this.compareFind(index + 1, start + 1, left ,right);
- val.find = true;
- val.series += rtn.series + 1;
- }
- }
-
- return val;
- },
- this.compareNext = function (s1, s2, left, right, result) {
- let diff = {
- left: 0,
- series: 0,
- right: 0,
- find: false
- };
- for (let i=s1; i - s1 < this.findLen && i< left.length; i++) {
- let len = this.compareFind(i, s2, left, right);
- if (diff.series < len.series) {
- diff.left = i;
- diff.series = len.series;
- diff.right = len.right;
- }
- }
-
- if (diff.series > 0) {
- for (let i=s1;i<diff.left;i++) {
- result[i] = "<span style='background-color: pink'>" + left[i] + "</span>"; // 标记新增的部分
- }
-
- let r = diff.right;
- for (let i=diff.left; i<diff.left + diff.series;i++) {
- let score = this.difference(left[i], right[r++]);
- if (score < 100) {
- result[i] = "<span style='background-color: yellow'>" + left[i] + "</span>"; // 标记修改的部分
- } else {
- result[i] = left[i]; // 相同的部分
- }
- }
- diff.find = true;
- } else {
- // result.push("<span style='background-color: pink'>" + left[s1] + "</span>"); // 标记新增的部分
- if (s2 + 1 < right.length) {
- let f = this.compareNext(s1, s2 + 1, left, right, result);
- return {
- series: f.series,
- left: f.left,
- right: f.right,
- find: f.find
- }
- } else {
- diff.left = s1 + 1;
- diff.right = s2;
- }
- }
-
- return {
- series: diff.series,
- left: diff.left + diff.series,
- right: diff.right + diff.series,
- find: diff.find
- };
- },
- this.compareJson = function (left, right) {
- let result = [];
- let liftLine = this.json2Lines(left);
- let rightLine = this.json2Lines(right);
- let lIndex = 0, rIndex = 0;
- while (lIndex < liftLine.length) {
- let diff = this.compareNext(lIndex, rIndex, liftLine, rightLine, result);
- if (!diff.find) {
- result[lIndex] = "<span style='background-color: pink'>" + left[lIndex] + "</span>"; // 标记新增的部分
- }
- lIndex = diff.left;
- rIndex = diff.right;
- // break;
- }
-
- return result;
- },
- this.jsonToCompare = function (left, right) {
- try {
- //json对象排序
- let l = this.jsonSort(JSON.parse(left));
- let r = this.jsonSort(JSON.parse(right));
- let res = this.compareJson(l, r);
- return res.join(" ");
- } catch (e) {}
- return left;
- }
- }
- //调用例子
-
- let json1= {
- v1: "abc",
- v2: "ccc",
- v3: "ddd",
- v4: "555"
- }, json2= {
- v1: "abc",
- v2: "ccc",
- v3: "eee"
- }
- let cp = new compare();
-
- cp.jsonToCompare(json1, json2);
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。