资深工程师告诉你:数组去重办法远不止lodash
2023-12-14 13:03:29
许多时候,我们得到的数组数据可能会有重复元素,这时就需要我们对数组进行去重操作。而数组去重一直是前端面试的必考题,数组去重的算法并不复杂,但涉及到的细节却不少,值得仔细研究一番。
了解数组去重,首先需要了解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;
}
这个函数使用一个深比较的函数来实现数组去重。这个深比较的函数可以比较两个对象是否相等,无论这两个对象是基本类型还是引用类型。
总之,数组去重有多种方法,每种方法都有其优缺点。在实际开发中,我们可以根据具体的情况来选择合适的方法进行数组去重。