返回

资深工程师告诉你:数组去重办法远不止lodash

前端

许多时候,我们得到的数组数据可能会有重复元素,这时就需要我们对数组进行去重操作。而数组去重一直是前端面试的必考题,数组去重的算法并不复杂,但涉及到的细节却不少,值得仔细研究一番。

了解数组去重,首先需要了解JavaScript中的相等性判断规则。在JavaScript中,==和===是两个不同的运算符,==进行的是值比较,而===进行的是严格相等比较。这意味着,如果两个值类型相同,并且相等,那么==和===都会返回true;否则,它们都会返回false。

数组去重,最先想到的工具就是Lodash库。Lodash库是一个JavaScript工具库,提供了许多有用的函数,其中包括一个_.uniq()函数,可以用于数组去重。Lodash的去重函数采用的值比较规则是使用严格相等比较(===)。也就是说,如果数组中的两个元素严格相等,那么它们就会被认为是重复元素,并从数组中删除。

然而,Lodash的去重函数并不能满足所有的去重场景。例如,如果数组中的元素是一个对象,那么使用Lodash的去重函数并不能正确地去重。这是因为,对象是引用类型,两个对象即使属性值相同,但它们并不是同一个对象,因此使用严格相等比较会认为它们是不同的元素,从而不能正确地去重。

为了解决这个问题,我们可以使用ES6的Map结构来实现数组去重。Map是一种键值对的数据结构,它可以存储任意类型的值。我们可以将数组中的元素作为Map的键,然后使用Map的键唯一性来实现数组去重。

function unique(arr) {
  const map = new Map();
  for (const item of arr) {
    map.set(item, true);
  }
  return [...map.keys()];
}

这个函数使用Map来存储数组中的元素,然后使用Map的键唯一性来实现数组去重。需要注意的是,这个函数只能对基本类型的值进行去重,如果数组中的元素是一个对象,那么使用这个函数并不能正确地去重。

对于对象类型的数组去重,我们可以使用一个递归函数来实现。这个递归函数将数组中的每个元素都作为参数传递给自身,然后检查这个元素是否在数组中已经出现过。如果已经出现过,那么就将其从数组中删除;如果没有出现过,那么就将其添加到数组中。

function unique(arr) {
  const result = [];
  for (const item of arr) {
    if (!result.includes(item)) {
      result.push(item);
    }
  }
  return result;
}

这个函数使用一个递归函数来实现数组去重。需要注意的是,这个函数只能对基本类型的值进行去重,如果数组中的元素是一个对象,那么使用这个函数并不能正确地去重。

对于对象类型的数组去重,我们可以使用一个深比较的函数来实现。这个深比较的函数将两个对象进行比较,如果两个对象的属性值都相同,那么就认为这两个对象是相等的。我们可以使用这个深比较的函数来实现数组去重。

function unique(arr) {
  const result = [];
  for (const item of arr) {
    if (!result.some(x => deepEqual(x, item))) {
      result.push(item);
    }
  }
  return result;
}

function deepEqual(obj1, obj2) {
  if (obj1 === obj2) {
    return true;
  }
  if (typeof obj1 !== 'object' || obj1 === null ||
      typeof obj2 !== 'object' || obj2 === null) {
    return false;
  }
  if (Object.keys(obj1).length !== Object.keys(obj2).length) {
    return false;
  }
  for (const key in obj1) {
    if (!obj2.hasOwnProperty(key) || !deepEqual(obj1[key], obj2[key])) {
      return false;
    }
  }
  return true;
}

这个函数使用一个深比较的函数来实现数组去重。这个深比较的函数可以比较两个对象是否相等,无论这两个对象是基本类型还是引用类型。

总之,数组去重有多种方法,每种方法都有其优缺点。在实际开发中,我们可以根据具体的情况来选择合适的方法进行数组去重。