比较两个数组的差异?我是这么写的

·  阅读 2478

最近遇到一个需求,需要比较两个数组的差异,数组的每一项都是一个对象,包括数组长度的变更,要求增加和删除都能检测到,将结果用表格的形式展现出来;网上寻找到相关的文章都是过于简单的数组里面是纯数字的情况,在这里并不适用,没办法只好手撸一个函数来实现一下,在此做个记录。

废话不多说直接开干,假设现在有两个数组如下:

//变更前
const arr1 = [{
  name: '阿花',
  age: 19,
  city: '北京'
}, {
  name: '翠花',
  age: 17,
  city: '上海'
}, {
  name: '狗剩',
  age: 30,
  city: '杭州'
}];
//变更后
const arr2 = [{
  name: '大帅比',
  age: 25,
  city: '西安'
}, {
  name: '老帅比',
  age: 35,
  city: '成都'
}];
复制代码

可以看到这两个数组内容是完全不一样的,我们的需求是比较这两个数组的变更,那么如何来实现呢?

具体思路

  1. 我们先声明一个函数,设置好对应的形参用来接收变更前后的数组,并初始化函数的返回值
function comparison(previous, current) {
  //previous为变更前的数组,current为变更后的数组
  
  //定义好函数的返回值
  const result = [];
  return result;
}
复制代码

为什么这里选择用数组来作为返回值呢,其实想象一下就能明白,上面我们要求要用表格的形式展现出来,用数组可以方便渲染数据,同时数组的每一项都是一组变更,数组的长度就是变更的组数,这个我们后面会慢慢体现。

  1. 现在我们要开始撸具体的实现部分了,在此之前我们先拿到一些值:
  //获取变更的组数,len代表变更了多少组数据
  const len = Math.max(arr1.length, arr2.length);
  //获取用来遍历的数组
  const loopArr = arr1.length > arr2.length ? arr1 : arr2;
  //获取用来另一个用来对比的数组
  const preArr = arr1.length > arr2.length ? arr2 : arr1;
复制代码

为什么要这么写呢,len这个变量存储的是变更了多少组数据,同时拿loopArr用来遍历就不会出现遗漏的情况,因为loopArr的长度和len是相等的,这是只需要用preArr存一下另一组数据就好了。

  1. 现在开始我们的逻辑部分

比对之前先做一层判断,若没有发生变更就直接return掉,这一块也可以提到函数前面一进来就判断

//没有变更直接return
if (JSON.stringify(arr1) === JSON.stringify(arr2)) {
  return;
}
复制代码

这里使用的是JSON.stringify来对比,要注意对象属性值为undefined和函数的情况,因为JSON.stringify会忽略掉它们

函数执行到这里就说明发生了变更,我们先初始化每一组数据的变更:

for (let i = 0; i < len; i++) {
  result[i] = [];
}
复制代码

这里使用的是for循环来初始化,在vue的方法里写的话看着有点别扭,不知道有没有其他更简洁的写法,知道的小伙伴可以留个言哈

然后就开始我们的比对了,直接上码

loopArr.forEach((item, index) => {
  for( const key in item) {
    //增加和删除的情况默认为空对象
    preArr[index] || (preArr[index] = {});
    //如果不相等就定义一个对象并push到数组中
    if (item[key] !== preArr[index][key]) {
      const changedItem = {
        fieldName: key, //字段名
        preValue: arr1[index][key] || '', //变更前的值,取不到默认为空
        currentValue: arr2[index][key] || '',  //变更后的值
      }
      result[index].push(changedItem)
    }
  }
});
复制代码

比对结果

到这里逻辑部分就写完了,我们来执行comparison(arr1, arr2)看看结果: 可以看到变更的值都检测到了,同时增加和删除也能检测到,这里我们把它设置为空了,不然会显示undefined

最后我们再用表格的形式来展现结果,可以更加直观的对比差异 由于我的那个需求数组里每一个对象都是一组规则,现在不管是增加删除还是修改,都可以检测到规则的变更了

完整代码

最后附上完整代码:

 //变更前
  const arr1 = [{
    name: '阿花',
    age: 19,
    city: '北京'
  }, {
    name: '翠花',
    age: 17,
    city: '上海'
  }, {
    name: '狗剩',
    age: 30,
    city: '杭州'
  }];
  //变更后
  const arr2 = [{
    name: '大帅比',
    age: 25,
    city: '西安'
  }, {
    name: '老帅比',
    age: 35,
    city: '成都'
  }];
  
  
function comparison(previous, current) {
  //previous为变更前的数组,current为变更后的数组
  
  //定义好函数的返回值
  const result = [];
  //获取变更的组数,len代表变更了多少组数据
  const len = Math.max(arr1.length, arr2.length);
  //获取用来遍历的数组
  const loopArr = arr1.length > arr2.length ? arr1 : arr2;
  //获取用来另一个用来对比的数组
  const preArr = arr1.length > arr2.length ? arr2 : arr1;
  
  //没有变更直接return
  if (JSON.stringify(arr1) === JSON.stringify(arr2)) {
    return;
  }
  //初始化每一组数据的变更
  for (let i = 0; i < len; i++) {
    result[i] = [];
  }
  //遍历比对差异
  loopArr.forEach((item, index) => {
    for( const key in item) {
      //增加和删除的情况默认为空对象
      preArr[index] || (preArr[index] = {});
      //如果不相等就定义一个对象并push到数组中
      if (item[key] !== preArr[index][key]) {
        const changedItem = {
          fieldName: key, //字段名
          preValue: arr1[index][key] || '', //变更前的值,取不到默认为空
          currentValue: arr2[index][key] || '',  //变更后的值
        }
        result[index].push(changedItem)
      }
    }
  });
  return result;
}
  
复制代码

到这里整个过程就结束了,喜欢的朋友帮忙点个赞吧。

分类:
前端
标签: