数组去重是面试常见的题目,要么口述要么手写,也算较为简单的一道题目,但却有多种方法解答。不过在实际开发中,数据一般都被后端处理过了,到了前端这里数据很少 有需要去重的情况。
这里我们统一测试数据和调用方法如下:
var arr = [1,12,1,"asa","asb","as",NaN,NaN,undefined,null,null,undefined,"NaN","undefined","null","null","Nan","undefined",true,true,false,false,"true","false","true","false",{},{},{name:1},{name:1}];
unique(arr);
1.Es6新方法(Set去重)
无法对{}数据去重
function unique(arr){
return Array.from(new Set(arr));
}
// 结果: [1, 12, "asa", "asb", "as", NaN, undefined, null, "NaN", "undefined", "null", "Nan", true, false, "true", "false", {…}, {…}, {…}, {…}]
可利用“…”扩展运算符简化该方法。
无法对{}数据去重
function unique(arr){
return [...new Set(arr)];
}
// 结果:[1, 12, "asa", "asb", "as", NaN, undefined, null, "NaN", "undefined", "null", "Nan", true, false, "true", "false", {…}, {…}, {…}, {…}]
2.遍历数组使用indexOf()方法
这里遍历数组使用for,for…in,for…of,forEach都行,但要注意for…in是遍历下标。
无法对NaN和{}数据去重
function unique(arr){
var newArr = [];
arr.forEach(ele=>{
if(newArr.indexOf(ele) == -1){
newArr.push(ele);
}
})
return newArr;
}
// 结果:[1, 12, "asa", "asb", "as", NaN, NaN, undefined, null, "NaN", "undefined", "null", "Nan", true, false, "true", "false", {…}, {…}, {…}, {…}]
3.遍历数组使用includes()方法
无法对{}去重
function unique(arr){
var newArr = [];
arr.forEach(ele=>{
if(!newArr.includes(ele)){
newArr.push(ele);
}
})
return newArr;
}
// 结果:[1, 12, "asa", "asb", "as", NaN, undefined, null, "NaN", "undefined", "null", "Nan", true, false, "true", "false", {…}, {…}, {…}, {…}]
4.利用filter鉴别出现位置和下标相等过滤
原理:在数组中首次出现的位置和下标相同则过滤出来
无法对NaN和{}去重,且NaN消失。
function unique(arr){
return arr.filter((item,index) => {
return arr.indexOf(item) == index;
})
}
// 结果:[1, 12, "asa", "asb", "as", undefined, null, "NaN", "undefined", "null", "Nan", true, false, "true", "false", {…}, {…}, {…}, {…}]
5.利用对象Key值过滤
原理:利用的是对象的key值不能相同,最后输出key值。需要注意的是如果直接输出key值其类型均为字符串,如果这种结果不是你想要的,可以定义一个空数组,每次if执行时存取值。
NaN可去重,但是非字符串值会当作字符串值对待(NaN等同于"NaN"、true等同于"true")。
function unique(arr){
var obj = {};
arr.forEach(ele => {
if(!obj[ele]){
obj[ele]=1;
}
})
return Object.keys(obj);
}
// 结果:["1", "12", "asa", "asb", "as", "NaN", "undefined", "null", "Nan", "true", "false", "[object Object]"]
6.使用ES6的Map去重与方法5类似
无法对{}去重
function unique(arr){
let map = new Map();
let newArr = new Array();
arr.forEach(ele => {
if(map.has(ele)){
map.set(ele, 1);
}else{
map.set(ele, 0);
newArr.push(ele);
}
})
return newArr;
}
// 结果:[1, 12, "12", "asa", "asb", "as", NaN, undefined, null, "NaN", "undefined", "null", "Nan", true, false, "true", "false", {…}, {…}, {…}, {…}]
7.使用reduce()配合includes()去重,与上面遍历配合inclues()类同。
无法对{}去重
reduce()方法使用的不多,这里介绍一下:
用法:array.reduce(function(total, currentValue, currentIndex, arr), initialValue)
参数:total 必需。初始值, 或者计算结束后的返回值。
currentValue 必需。当前元素
currentIndex 可选。当前元素的索引
arr 可选。当前元素所属的数组对象。
initialValue 可选。传递给函数的初始值结果:返回total
function unique(arr){
return arr.reduce(function(total, current){
return total.includes(current) ? total : [...total, current];
},[]); // 初始值为空数组
}
// 结果:[1, 12, "12", "asa", "asb", "as", NaN, undefined, null, "NaN", "undefined", "null", "Nan", true, false, "true", "false", {…}, {…}, {…}, {…}]
其他方法与以上几种类同,这里不再做其他演变。