题目如下:
此题就是比较两个JSON数据是否深度相等,这在日常开发中处理树形JSON还是比较容易遇到的。
我的思路是在areDeeplyEqual函数中定义一个标识是否相等的变量isEqual为true,然后在接下来的逻辑中检查每个值是否相等,遇到不相等的时候将isEqual置为false,而且一旦isEqual置为false时,接下来的执行也就没有比较再继续了,return停止执行后续都有逻辑执行。由于是深层JSON,需要递归执行,所以areDeeplyEqual函数中定义一个compare比较函数。
主要的核心逻辑在compare函数里,按照o1和o2的数据类型来进行不同的比较策略,当遇到子项依然是对象或数组时,则将子项递归执行compare比较。
为了避免较为重复和繁琐的类型判断,实现judgeType函数来判定数据类型,主要为了能很好地区分null、对象、数组和简单类型。
代码如下:
const entries = obj => Object.entries(obj);
// 重写一个判断数据类型的函数
const judgeType = val => {
if (val === null) return 'NULL';
if (Array.isArray(val)) return 'ARRAY';
if (val !== null && typeof val === 'object') return 'OBJECT';
return typeof val;
}
var areDeeplyEqual = function (o1, o2) {
// 一开始设定是否等于标识为true
let isEqual = true;
// 比较函数
const compare = (o1, o2) => {
// 如果两个值类型不同,肯定不相等
if (judgeType(o1) !== judgeType(o2)) {
console.log('28');
isEqual = false;
return;
} else if ((typeof o1 !== 'object' && typeof o2 !== 'object') && o1 !== o2) {
// 如果是基本类型的话,直接比较,如果严格不等于,isEqual置为false
isEqual = false;
return;
} else if (judgeType(o1) === 'OBJECT' && judgeType(o2) === 'OBJECT') {
// 如果两个都是非数组的对象
if (entries(o1).length !== entries(o2).length) {
// 对象的key数不一样多,肯定不相等
isEqual = false;
return;
} else {
// 两个对象的key数一样多时,需要对比key-value值是否匹配
entries(o1).forEach(([key, val]) => {
if (['OBJECT', 'ARRAY'].includes(judgeType(val))) {
// 如果当前属性的value依然是对象或数字,则递归执行比较
compare(val, o2[key]);
} else if (val !== o2[key]) {
// 如果是简单类型,则直接比较是否相等
isEqual = false;
return;
}
});
}
} else if (judgeType(o1) === "ARRAY" && judgeType(o2) === "ARRAY") {
// 如果两个都是数组类型
if (o1.length !== o2.length) {
// 长度相等,则isEqual置为false
isEqual = false;
return;
}
// 如果长度相等,则需要遍历比较数组的每个元素是否对应相等
o1.forEach((item, index) => {
if (['OBJECT', 'ARRAY'].includes(judgeType(item))) {
// 如果当前元素依然是对象或数字,则递归执行比较
compare(item, o2[index]);
} else if (item !== o2[index]) {
// 如果是简单类型,则直接比较是否相等
isEqual = false;
return;
}
});
}
};
// 还是执行比较函数
compare(o1, o2);
// 返回是否相等的标识
return isEqual;
};
此实现执行效率不如力扣官方给出的实现高,但思维难度较小,容易想到,并且通过区分不同类型来做不同的比较策略,这个思路较为简单清晰,所以记录一下。


Comments | NOTHING