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

//变更前
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 = [];
      return 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;
    

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

  • 现在开始我们的逻辑部分 比对之前先做一层判断,若没有发生变更就直接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;
    

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

    分类:
    前端
    标签: