js数组去重复的数据(js数组去重最简单的方法)


无论是在面试还是在项目开发中,数组去重是经常碰到的问题。今天老K为大家总结一下几种好用的数组去重的方法。

ES5的方法:

一、利用两次for循环,然后splice去重(ES5中最常用)

function unique(arr){
 if(toString.call(arr) !== "[object Array]"){
 console.log('必须为数组');
 return ;
 }
 for(var i=0; i<arr.length; i++){
 for(var j = i+1; j<arr.length; j++){
 if(arr[i] === arr[j]){ //第一个等同于第二个,splice方法删除第二个
 arr.splice(j,1);
 j--;
 }
 }
 }
 return arr;
};
var arr = [2,2,'a','a',true,true,'true','true',false,false,'false','false',undefined,undefined,null,null,NaN,NaN,'NaN',0,0,{},{}];
unique(arr); // [2, "a", true, "true", false, "false", undefined, null, NaN, NaN, "NaN", 0, {…}, {…}]

原理:双层循环,外层循环元素,内层循环时比较值。值相同时,则删去这个值。

优点:兼容强。

缺点:不能去重NaN,object对象,数据量大时,效率不高。

二、利用数组的排序方法sort去重

function unique(arr){
 if (toString.call(arr) !== "[object Array]"){
 console.log('必须为数组');
 return;
 }
 arr = arr.sort()
 var new_array = [arr[0]];
 for(var i =1; i<arr.length; i++){
 if(arr[i] !== arr[i-1]){
 new_array.push(arr[i]);
 }
 }
 return new_array;
};
var arr = [2,2,'a','a',true,true,'true','true',false,false,'false','false',undefined,undefined,null,null,NaN,NaN,'NaN',0,0,{},{}];
unique(arr);//[0, 2, NaN, NaN, "NaN", {…}, {…}, "a", false, "false", null, true, "true", undefined]

原理:利用sort()排序方法,然后根据排序后的结果进行遍历及相邻元素比对。

优点:兼容强,逻辑简单,容易理解。

缺点:不能去重NaN,object对象。

三、利用对象的属性不能相同的特点进行去重,主要用hasOwnProperty

function unique(arr){
 if (toString.call(arr) !== "[object Array]"){
 console.log('必须为数组');
 return;
 }
 var obj = {};
 var new_arr = [];
 for(var i = 0; i< arr.length; i++){
 if(!obj.hasOwnProperty(typeof arr[i]+arr[i])){
 new_arr.push(arr[i]);
 obj[typeof arr[i]+arr[i]] = true;
 }
 }
 return new_arr
}
var arr = [2,2,'a','a',true,true,'true','true',false,false,'false','false',undefined,undefined,null,null,NaN,NaN,'NaN',0,0,{},{}];
unique(arr); //[2, "a", true, "true", false, "false", undefined, null, NaN, "NaN", 0, {…}]

原理:新建个空对象,空数组,遍历目标数组。如果元素不是对象的键,将元素加到新数组里,同时给键赋值。如果已是对象的键,则忽略。利用typeof 区分布尔值和”true”、“false“,NaN和“NaN“。

优点:可以将各种类型的数据去重。

缺点:暂无。

ES6的方法:

一、 利用 ES6的Set对象的特性去重

function unique(arr){
 if(!Array.isArray(arr)){
 console.log('必须为数组');
 return;
 }
 return Array.from(new Set(arr)) //或者用扩展运算符转化为数组 return [...new Set(arr)]
};
var arr = [2,2,'a','a',true,true,'true','true',false,false,'false','false',undefined,undefined,null,null,NaN,NaN,'NaN',0,0,{},{}];
unique(arr); // [2, "a", true, "true", false, "false", undefined, null, NaN, "NaN", 0, {...},{...}]

原理:利用ES6的Set对象自动排除重复项的特性,通过ES6的Array的from方法或者扩展运算符将Set对象转化为数组。

优点:不考虑兼容性,这种方法代码最少。

缺点:这种方法无法去重object对象,需要考虑兼容问题。

二、利用ES6的数组方法indexOf去重

function unique(arr){
 if(!Array.isArray(arr)){
 console.log('必须为数组');
 return;
 }
 var new_array = [];
 for(var i = 0; i< arr.length; i++){
 if (new_array.indexOf(arr[i]) === -1){
 new_array.push(arr[i])
 }
 }
 return new_array;
};
var arr = [2,2,'a','a',true,true,'true','true',false,false,'false','false',undefined,undefined,null,null,NaN,NaN,'NaN',0,0,{},{}];
unique(arr); //[2, "a", true, "true", false, "false", undefined, null, NaN, NaN, "NaN", 0, {…}, {…}]

原理:新建一个空的结果数组,for 循环原数组,利用indexOf方法判断结果数组是否存在当前元素,如果有相同的值则跳过,不相同则push进数组。

优点:利用ES6数组的新方法,逻辑简单,容易理解。

缺点:不能去重NaN,object对象,需要考虑兼容问题。

三、利用ES6的数组方法includes去重

function unique(arr){
 if(!Array.isArray(arr)){
 console.log('必须为数组');
 return;
 }
 var new_array = [];
 for(var i = 0; i< arr.length; i++){
 if ( !new_array.includes(arr[i]) ){
 new_array.push(arr[i]) 
 }
 }
 return new_array;
};
var arr = [2,2,'a','a',true,true,'true','true',false,false,'false','false',undefined,undefined,null,null,NaN,NaN,'NaN',0,0,{},{}];
unique(arr); //[2, "a", true, "true", false, "false", undefined, null, NaN, "NaN", 0, {…}, {…}]

原理:创建个新的空数组new_array,遍历目标数组,利用includes方法判断目标数组的元素是否在新数组里,如果没有,将元素添加到新数组中,如果有则忽略。

优点:利用ES6数组的新方法,逻辑简单,容易理解。

缺点:不能去重object对象,需要考虑兼容性。

四、利用ES6的filter和indexOf去重

function unique(arr){
 if(!Array.isArray(arr)){
 console.log('必须为数组');
 return;
 }
 return arr.filter(function(item, index, arr){
 return arr.indexOf(item, 0) === index;
 });
}
var arr = [2,2,'a','a',true,true,'true','true',false,false,'false','false',undefined,undefined,null,null,NaN,NaN,'NaN',0,0,{},{}];
unique(arr); //[2, "a", true, "true", false, "false", undefined, null, "NaN", 0, {…}, {…}]

原理:给filter一个过滤条件,获取元素在原始数组的第一个索引,如果等于当前索引值,返回当前元素。

优点:利用ES6数组的新方法,逻辑简单,容易理解。

缺点:不能去重object对象和NaN,需要考虑兼容性。

五、利用ES6的Map数据格式去重

function unique(arr){
 if(!Array.isArray(arr)){
 console.log('必须为数组');
 return;
 }
 let map = new Map();
 let new_array = new Array();
 for(let i = 0; i<arr.length; i++){
 if(map.has(arr[i])){
 map.set(arr[i], true);
 }else{
 map.set(arr[i], false);
 new_array.push(arr[i]);
 }
 }
 return new_array;
}
var arr = [2,2,'a','a',true,true,'true','true',false,false,'false','false',undefined,undefined,null,null,NaN,NaN,'NaN',0,0,{},{}];
unique(arr); //[2, "a", true, "true", false, "false", undefined, null, NaN, "NaN", 0, {…}, {…}]

原理:创建一个新数组,遍历目标数组,如果元素没有在Map里,则添加到新数组。

优点:利用ES6数组的新数据结构,逻辑简单,容易理解。

缺点:不能去重object对象,需要考虑兼容性。

六、利用ES6的reduce和includes去重

function unique(arr){
 if(!Array.isArray(arr)){
 console.log('必须为数组');
 return;
 }
 return arr.reduce( (prev, cur) => prev.includes(cur) ? prev : [...prev,cur], []);
}
var arr = [2,2,'a','a',true,true,'true','true',false,false,'false','false',undefined,undefined,null,null,NaN,NaN,'NaN',0,0,{},{}];
unique(arr); //[2, "a", true, "true", false, "false", undefined, null, NaN, "NaN", 0, {…}, {…}]

原理:创建一个新数组,遍历目标数组,如果元素没有在Map里,则添加到新数组。

优点:利用ES6数组的reduce,设置初始值为一个空数组,迭代判断当前元素是否在上一个数组中,如果有则返回上一个数组,没有则把当前元素添加到上一个元素中然后返回一个新数组。

缺点:不能去重object对象,需要考虑兼容性。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发表评论

登录后才能评论