likes
comments
collection
share

新旧数组对比,找出不同的元素

作者站长头像
站长
· 阅读数 9

前言

项目中有个用户自定义配置表单的功能,可以让用户决定这个表单中要什么字段、字段是什么类型等等,这些表单信息使用数组保存起来,展示的时候通过v-for遍历渲染,这是背景。 现在要加一个需求,就是判断用户做出了哪些更改,删除了哪些字段、新增了哪些字段、更改了哪些字段的配置等等。 本文主要记叙了对比用户更改前的表单信息数组和用户更改后的表单信息数组,找出其中的删除的元素和新增的元素。

基本思路

暂且将更改前的表单信息数组称为ArrayBefore,将更改后的表单信息数组称为ArrayAfter,两个都是一维的对象数组。 不管是删除还是新增,说白了就是找不同,看看某个值哪个数组有,而哪个数组没有而已;如果ArrayBefore有,而ArrayAfter没有,那就是删除的;反过来,则是新增。 也可以反过来思考,就是找相同,排除相同的,剩下的就是不同,本文也是使用这种思路。 最直接的做法肯定是遍历ArrayBefore,用ArrayBefore中字段去ArrayAfter中寻找,这样就是双层循环,;ArrayAfter也是同样的处理,这种方法比较直接,但是效率也不高。 但有一个更好的方法,两个数组遍历一次即可,思路是:

  1. 先将其中一个数组循环遍历,转换成Map映射表;
  2. 遍历另一个数组,将遍历到的元素和Map中进行查找,如果存在,数组和Map同时删除该字段;如果Map表中没有,不进行任何操作。
  3. 最终Map中还剩下的就是新增或者删除,而数组中的剩下的,就是另一种类型。

代码

为了方便测试,将测试数据设为以下两个数组:

const arrayBefore = [1,3,4,8,6,7]
const arrayAfter = [2,4,3,1,9,8]

首先,将其中一个数组转换为Map,本文中将arrayAfter转换为Map(因为arrayAfter过后还需要进行其他操作,不宜更改),也就是说,经过对比之后,Map还存在的就是新增的,arrayBefore中还存在就是删除的:

function check(arrayBefore, arrayAfter) {
  // 创建Map
  const map = new Map()
  // 第一次循环,将arrayAfter转换为Map
  for (let i = 0, len = arrayAfter.length; i < len; i++) {
    map.set(arrayAfter[i], arrayAfter[i])
  }
}

接下来,自然就是循环遍历的arrayBefore,将之中的数据与Map进行对比,如果存在相同的元素,就一起将其删除:

function check(arrayBefore, arrayAfter) {
  const map = new Map()
  for (let i = 0, len = arrayAfter.length; i < len; i++) {
    map.set(arrayAfter[i], arrayAfter[i])
  }

  // 第二次遍历,将arrayBefore中数据与Map进行对比
  for (let i = 0, len = arrayBefore.length; i < len; i++) {
    const item = arrayBefore[i] 
    if (map.has(item)) {
      // 如果Map中存在相同的数据,则一起删除
      arrayBefore[i] = false
      map.delete(item)
    }
  }
}

打印最终结果:

console.log('新增的:', Array.from(map.keys()))
// ===> 新增的: (2) [2, 9]
console.log('删除的:', arrayBefore.filter(item => item))
// ===> 删除的: (2) [6, 7]