题目如下:
此题就是比较两个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