JS二维数组去重(针对简单的数据结构)

335 阅读3分钟

摘要: 相较于一维数组,二维数组中两个数组的去重不能使用Set,而判断两个数组元素是否相同也很麻烦。因此需要有二维数组去重的算法。

1.当二维数组中的数组中均为纯数字数组时

function numberUnique(martix) {
  let res = {};
  martix.forEach((item) => {
    item.sort((a, b) => a - b); // 先使其降序排序
    res[item] = item; // 当传入的是[1,2]时,打印为{'1,2':[1,2]}
  })
  return Object.values(res);
}

基本思路:

  1. 为一个对象的key值赋值一个Object或者Array对象时,会调用.toString()方法,因此原本相同元素的数组比如[1, 2][1,2]都会变为'1,2',此时就达到了我们想要的去重的效果(值得注意的是如果给对象的key赋值对象,相当于将key值设置为[Objcet, Object]),因此我们先排序使每个数组都升序排列。
  2. 由于数组存储的每一个value值就为我们想要的数组,因此返回Object.values(res)就是我们想要的去重数组。

缺陷:由于sort中函数的写法,无法对字符串数组进行排序,也无法对复杂数据类型进行去重。

2.当二维数组中的数组中均为纯字符串数组时

function strUnique(matrix) {
  let res = [];
  matrix.forEach(item => {
    res.push(item.sort((a, b) => a.localeCompare(b)).join());
  })
  return [...new Set(res)].map(item => item.split(','));
}

基本思路:

  1. 相比于纯数字数组,字符串数组可以先合为一个‘整体’字符串,再进行拆分,这是其独有的优势。
  2. 将字符串数组排序后再合并存入res数组中,此时res数组相当于一个一维数组可以使用Set方法去重。最后再拆分即可。
  3. 使用localCompare方法可以对字符串进行比较,一般不会单独使用,可以在排序时使用。该方法传入一个比较字符串,如果原字符串(除了unicode还可以自己创建规则)大于比较字符串返回1,小于返回0,不然返回-1,当然有可能有其他值,因此不能简单地利用返回值===1或-1来判断字符串的大小。

缺陷:

  1. 同样地由于sort中函数的写法,无法对数字数组进行排序,也无法对复杂数据类型进行去重。当二维函数兼有纯数字数组与纯字符串数组或者一维数组中既存在数字又存在字符串时也无法使用。
  2. 由于split(',')的使用,如果原来的字符串数组中存在','时也会被分割,返回的数组与原数组不同。

3.二者的升级版

function unique(martix) {
  let res = {};
  const sortRole = (a, b) => {
    if(typeof a === "number" && typeof b === "number")  return a - b;
    else if (typeof a === "number" && typeof b === "string") return 1;
    else if (typeof a === "string" && typeof b === "number") return -1;
    else if (typeof a === "string" && typeof b === "string") {
      return a.localeCompare(b);
    }
  }
  martix.forEach((item) => {
    item.sort(sortRole); 
    res[item] = item; 
  })
  return Object.values(res);
}

基本思路:纯数字数组不能对字符串数组排序的原因就是因为sort方法中传入函数的问题,因此可以对传入的数据类型进行判断即可。同时对比纯字符串类型的数组去重,这种方法也不会由于字符串中存在','而产生问题,基本实现了对于简单数据类型的二维数组的去重。