数组去重?
著名面试题:
如何实现数组去重?
包括:
- 使用set
- 使用Map
- 不用Map,Set(使用循环+各种API)
方法1: es6-set
function unique (arr) {
return Array.from(new Set(arr))
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{},{"name":"xixi"},{"name":"xixi"},{"name":"haha"}];
console.log(unique(arr))
//[1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {}, {},{"name":"xixi"},{"name":"xixi"},{"name":"haha"}]
- Array.from():方法从一个类似数组或可迭代的对象(包括 Array,Map,Set,String,TypedArray,arguments 对象等等) 中创建一个新的数组实例。
- Set对象:
ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。
Set 对象允许你存储任何类型的 唯一值 ,无论是原始值或者是对象引用。
Set对象是值的集合,你可以按照插入的顺序迭代它的元素。
Set中的元素只会出现一次,即 Set 中的元素是唯一的
- 缺点: 兼容性不好。无法去除对象重复。
方法2: es6-扩展运算符
function unique(arr){
return [...new Set(arr)];
}
// const unique = arr => [...new Set(arr)];
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{},{"name":"xixi"},{"name":"xixi"},{"name":"haha"}];
console.log(unique(arr))
//结果和上一种方法一样,只不过简单了
方法3: es6-map
function unique(arr) {
let map = new Map();
let res = new Array(); // 数组用于返回结果
for (let i = 0; i < arr.length; i++) {
if( map.has(arr[i])) { // 如果有该key值
map.set(arr[i], true);
} else {
map.set(arr[i], false); // 如果没有该key值
res.push(arr[i]);
}
}
return res
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{},{"name":"xixi"},{"name":"xixi"},{"name":"haha"}];
console.log(unique(arr))
- map的用法:www.cnblogs.com/yuer2018072…
- 缺点: 和前两种方法一样,无法去除对象。
方法4: 双层循环+splice
双层循环,外层循环元素,内层循环时比较值。值相同时,则删去这个值。
function unique(arr){
for (let i =0; i<arr.length;i++){
for (let j = i+1; j< arr.length;j++){
if(arr[i] === arr[j]){
arr.splice(j,1)
j--
console.log("j",j)
console.log("length",arr.length)
}
console.log(arr.length)
}
}
return arr
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{},{"name":"xixi"},{"name":"xixi"},{"name":"haha"}];
console.log(unique(arr))
// [1, "true", true, 15, false, undefined, null, NaN, NaN, "NaN", 0, "a", {}, {}, {"name":"xixi"},{"name":"xixi"},{"name":"haha"}]
缺点:无法去除重复的 NaN和对象
方法4: 单层循环+sort
利用sort()排序方法,然后根据排序后的结果进行遍历及相邻元素比对。
function unique(arr){
if(Object.prototype.toString.call(arr) !=='[object Array]'){
console.log('type error')
return
}
arr.sort()
var result =[]
for (let i =0;i <arr.length -1;i++){
if(arr[i] !== arr[i+1]){
result.push(arr[i])
}
}
result.push(arr[arr.length - 1])
return result
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{},{"name":"xixi"},{"name":"xixi"},{"name":"haha"}];
console.log(unique(arr))
//[0, 1, 15, NaN, NaN, "NaN",{},{},{"name":"xixi"},{"name":"xixi"},{"name":"haha"}, "a", false, null, "true", true, undefined]
缺点: 无法去除NaN和对象
方法5: 单层循环+ indexOf
新建一个空的结果数组,for 循环原数组,判断结果数组是否存在当前元素,如果有相同的值则跳过,不相同则push进数组。
function unique(arr){
if(Object.prototype.toString.call(arr) !=='[object Array]' ){
console.log('type error')
return
}
var result = []
for(let i =0;i < arr.length;i++){
if(result.indexOf(arr[i])=== -1){
result.push(arr[i])
}
}
return result
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{},{"name":"xixi"},{"name":"xixi"},{"name":"haha"}];
console.log(unique(arr))
// [1, "true", true, 15, false, undefined, null, NaN, NaN, "NaN", 0, "a",{},{},{"name":"xixi"},{"name":"xixi"},{"name":"haha"}]
缺点: 无法去除NaN和对象
对象的key+ forEach
对象的key
。
var arr = [1, 2, 3, 1, 1, 1, 3, 5, 3];
var obj = {};
var newArr = [];
arr.forEach((v) => {
if(!obj[v]) {
obj[v] = 1;
newArr.push(v);
}
})
console.log(newArr); // [1, 2, 3, 5]