题开始,数组去重,即从一个数组中移除所有重复的元素,确保每个元素只出现一次,是这一类问题的核心。
1. filter() 方法配合 indexOf()
const uniqueArray=array.filter((item, index, self)=> {
return self.indexOf(item)===index;
});
该方法利用 filter() 遍历数组,对于每个元素,通过 indexOf() 查找其在原数组中的第一个索引。如果当前元素的索引与正在遍历的索引相同,说明这是该元素在数组中的首次出现,保留该元素;否则,忽略该元素。
2. reduce() 方法
const uniqueArray=array.reduce((acc, current)=> {
return acc.includes(current) ? acc : [...acc, current];
}, []);
这里使用 reduce() 函数将数组累积到一个新的数组(acc)中。在每次迭代中,检查当前元素是否已存在于累积数组中。若不存在,则将其添加至累积数组;否则,跳过该元素。
1. 使用扩展运算符与解构赋值
const uniqueArray=[...new Set(array)];
这种方法简洁高效,利用 ES6 的 Set 数据结构自动去除重复元素的特性,再通过扩展运算符将 Set 转换回数组。Set 是一种特殊的集合,不允许重复元素存在,因此插入过程会自动过滤重复项。
2. 利用 Map 数据结构
const uniqueArray=Array.from(new Map(array.map(item=> [item, item])).values());
尽管不如直接使用 Set 直观,但此方法同样有效。它首先将数组映射为键值对相同的 Map,由于 Map 键的唯一性,重复的数组元素会被自动忽略。然后通过 Array.from() 和 Map.values() 将 Map 的值(即无重复元素)转换回数组。
1. 双重循环
const uniqueArray=[];
for (let i=0; i < array.length; i++) {
let isDuplicate=false;
for (let j=0; j < i; j++) {
if (array[i]===array[j]) {
isDuplicate=true;
break;
}
}
if (!isDuplicate) {
uniqueArray.push(array[i]);
}
}
这种方法最直观也最基础,通过外层循环遍历数组,内层循环检查当前元素是否与之前的所有元素重复。如果没有重复,则将其添加到结果数组中。虽然理解简单,但时间复杂度较高,不适用于大型数据集。
2. 利用对象作为哈希表
const uniqueArray=[];
const hashTable={};
for (let i=0; i < array.length; i++) {
const item=array[i];
if (!hashTable[item]) {
uniqueArray.push(item);
hashTable[item]=true;
}
}
这种方法利用对象作为哈希表,以数组元素作为键。在遍历过程中,若元素尚未作为对象的键存在,则添加到结果数组并将其设置为哈希表的键。由于对象属性查找的时间复杂度接近 O(1),这种方法在处理大量数据时比双重循环更为高效。
1. 性能比较
2. 优化策略
let arr=["头条", "头条", "头条", "plzbefat", "plzbefat", "plzbefat"];
let arrUnique=arr.filter((v, i, self)=> self.indexOf(v)===i); //过滤掉已经存在的值
console.log(arrUnique);
let arr=["头条", "头条", "头条", "plzbefat", "plzbefat", "plzbefat"];
let arrUnique=[...new Set(arr)];//值的集合 不能重复
console.log(arrUnique);
关于set函数:
Set 对象允许你存储任何类型的唯一值,无论是原始值或者是对象引用。
已知如下数组: var arr=[ [1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14] ] ] ], 10]; 编写一个程序将数组扁平化去并除其中重复部分数据,最终得到一个升序且不重复的数组
组实例的 flat(),flatMap()
数组的成员有时还是数组,Array.prototype.flat()用于将嵌套的数组“拉平”,变成一维的数组。该方法返回一个新数组,对原数据没有影响。
上面代码中,原数组的成员里面有一个数组,flat()方法将子数组的成员取出来,添加在原来的位置。
flat()默认只会“拉平”一层,如果想要“拉平”多层的嵌套数组,可以将flat()方法的参数写成一个整数,表示想要拉平的层数,默认为1。
上面代码中,flat()的参数为2,表示要“拉平”两层的嵌套数组。
如果不管有多少层嵌套,都要转成一维数组,可以用Infinity关键字作为参数。
如果原数组有空位,flat()方法会跳过空位
flatMap()方法对原数组的每个成员执行一个函数(相当于执行Array.prototype.map()),然后对返回值组成的数组执行flat()方法。该方法返回一个新数组,不改变原数组。
flatMap()方法的参数是一个遍历函数,该函数可以接受三个参数,分别是当前数组成员、当前数组成员的位置(从零开始)、原数组。
然后,我们来看看文章开始的那道题目如何优雅的求解
如果你还有好的方法,欢迎在下面留言,我会补充上去,供大家学习参考
参考文章:
https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/8
*请认真填写需求信息,我们会在24小时内与您取得联系。