js数组去重的常用方法总结


Posted in Javascript onJanuary 24, 2014

JS实现数组去重(重复的元素只保留一个)

1、遍历数组法

1.遍历数组法

它是最简单的数组去重方法(indexOf方法)

实现思路:新建一个数组,遍历去要重的数组,当值不在新数组的时候(indexOf为-1)就加入该新数组中;

例子1

function unique(arr) {
  if (!Array.isArray(arr)) {
    console.log('type error!')
    return
  }
  var array = [];
  for (var i = 0; i < arr.length; i++) {
    if (array .indexOf(arr[i]) === -1) {
      array .push(arr[i])
    }
  }
  return array;
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr))
  // [1, "true", true, 15, false, undefined, null, NaN, NaN, "NaN", 0, "a", {…}, {…}] //NaN、{}没有去重

例子2

var arr=[2,8,5,0,5,2,6,7,2];
function unique1(arr){
 var hash=[];
 for (var i = 0; i < arr.length; i++) {
   if(hash.indexOf(arr[i])==-1){
   hash.push(arr[i]);
   }
 }
 return hash;
}

2.数组下标判断法

调用indexOf方法,性能和方法1差不多

实现思路:如果当前数组的第 i 项在当前数组中第一次出现的位置不是 i,那么表示第 i 项是重复的,忽略掉。否则存入结果数组。

function unique2(arr){
 var hash=[];
 for (var i = 0; i < arr.length; i++) {
   if(arr.indexOf(arr[i])==i){
   hash.push(arr[i]);
   }
 }
 return hash;
}

3.排序后相邻去除法

实现思路:给传入的数组排序,排序后相同的值会相邻,然后遍历排序后数组时,新数组只加入不与前一值重复的值。

function unique3(arr){
 arr.sort();
 var hash=[arr[0]];
 for (var i = 1; i < arr.length; i++) {
   if(arr[i]!=hash[hash.length-1]){
   hash.push(arr[i]);
   }
 }
 return hash;
}

4.优化遍历数组法(不推荐)

实现思路:双层循环,外循环表示从0到arr.length,内循环表示从i+1到arr.length

将没重复的右边值放入新数组。(检测到有重复值时终止当前循环同时进入外层循环的下一轮判断)

function unique4(arr){
 var hash=[];
 for (var i = 0; i < arr.length; i++) {
  for (var j = i+1; j < arr.length; j++) {
   if(arr[i]===arr[j]){
    ++i;
   }
  }
   hash.push(arr[i]);
 }
 return hash;
}

上面遍历经过测试后有bug,并不能完全去重

js数组去重的常用方法总结

因为这次我做的是对js对象元素去重,我在参考时发现此bug,如果时数组去重,建议用第一种方法。

js数组去重的常用方法总结

quan_lst 里面是一个一个的js字面量对象,根据json里面的属性进行判定去重

function unique(quan_lst){  
//去掉重复选取的数据
  for (var i = 0; i < quan_lst.length; i++) {
    for (var j =i+1; j <quan_lst.length; ) {
      if (quan_lst[i].photoid == quan_lst[j].photoid ) {//通过photoid属性进行匹配;
        quan_lst.splice(j, 1);//去除重复的对象;
      }else {
        j++;
      }
    }
  }
}

5.ES6实现

基本思路:ES6提供了新的数据结构Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。

Set函数可以接受一个数组(或类似数组的对象)作为参数,用来初始化。

function unique5(arr){
 var x = new Set(arr);
 return [...x];
}

利用ES6 Set去重(ES6中最常用)

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',{},{}];
console.log(unique(arr))
 //[1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {}, {}]

扩展:如果重复,则去掉该元素

数组下标去重

function unique22(arr){
 var hash=[];
 for (var i = 0; i < arr.length; i++) {
   if(arr.indexOf(arr[i])==arr.lastIndexOf(arr[i])){
   hash.push(arr[i]);
   }
 }
 return hash;
}

补充:原先自己一直以为indexOf是针对字符串,原来indexOf也可以查询出数组元素所在的数组中的位置(以0开始计算),
以上转自于轩悦的博客,学了很多思路。

6、利用sort()

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

function unique(arr) {
  if (!Array.isArray(arr)) {
    console.log('type error!')
    return;
  }
  arr = arr.sort()
  var arrry= [arr[0]];
  for (var i = 1; i < arr.length; i++) {
    if (arr[i] !== arr[i-1]) {
      arrry.push(arr[i]);
    }
  }
  return arrry;
}
   var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
    console.log(unique(arr))
// [0, 1, 15, "NaN", NaN, NaN, {…}, {…}, "a", false, null, true, "true", undefined]   //NaN、{}没有去重

7、利用includes

includes 检测数组是否有某个值

function unique(arr) {
  if (!Array.isArray(arr)) {
    console.log('type error!')
    return
  }
  var array =[];
  for(var i = 0; i < arr.length; i++) {
      if( !array.includes( arr[i]) ) {//includes 检测数组是否有某个值
          array.push(arr[i]);
       }
  }
  return array
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
  console.log(unique(arr))
  //[1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {…}, {…}]   //{}没有去重

八、利用for嵌套for,然后splice去重(ES5中最常用)推荐

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

function unique(arr){      
    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 = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
  console.log(unique(arr))
  //[1, "true", 15, false, undefined, NaN, NaN, "NaN", "a", {…}, {…}]   //NaN和{}没有去重,两个null直接消失了

9、利用对象的属性不能相同的特点进行去重(这种数组去重的方法有问题,不建议用,有待改进)

function unique(arr) {
  if (!Array.isArray(arr)) {
    console.log('type error!')
    return
  }
  var arrry= [];
   var obj = {};
  for (var i = 0; i < arr.length; i++) {
    if (!obj[arr[i]]) {
      arrry.push(arr[i])
      obj[arr[i]] = 1
    } else {
      obj[arr[i]]++
    }
  }
  return arrry;
}
  var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
    console.log(unique(arr))
//[1, "true", 15, false, undefined, null, NaN, 0, "a", {…}]  //两个true直接去掉了,NaN和{}去重

十、利用hasOwnProperty

利用hasOwnProperty 判断是否存在对象属性

function unique(arr) {
  var obj = {};
  return arr.filter(function(item, index, arr){
    return obj.hasOwnProperty(typeof item + item) ? false : (obj[typeof item + item] = true)
  })
}
  var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
    console.log(unique(arr))
//[1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {…}]  //所有的都去重了

十一、利用filter

function unique(arr) {
 return arr.filter(function(item, index, arr) {
  //当前元素,在原始数组中的第一个索引==当前索引值,否则返回当前元素
  return arr.indexOf(item, 0) === index;
 });
}
  var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
    console.log(unique(arr))
//[1, "true", true, 15, false, undefined, null, "NaN", 0, "a", {…}, {…}]

十二、利用递归去重

function unique(arr) {
    var array= arr;
    var len = array.length;

  array.sort(function(a,b){  //排序后更加方便去重
    return a - b;
  })

  function loop(index){
    if(index >= 1){
      if(array[index] === array[index-1]){
        array.splice(index,1);
      }
      loop(index - 1);  //递归loop,然后数组去重
    }
  }
  loop(len-1);
  return array;
}
 var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr))
//[1, "a", "true", true, 15, false, 1, {…}, null, NaN, NaN, "NaN", 0, "a", {…}, undefined]

十三、利用Map数据结构去重

创建一个空Map数据结构,遍历需要去重的数组,把数组的每一个元素作为key存到Map中。由于Map中不会出现相同的key值,所以最终得到的就是去重后的结果。

function unique(arr){
  return arr.reduce((prev,cur) => prev.includes(cur) ? prev : [...prev,cur],[]);
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr));
// [1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {…}, {…}]

十四、利用reduce+includes

function unique(arr){
  return arr.reduce((prev,cur) => prev.includes(cur) ? prev : [...prev,cur],[]);
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr));
// [1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {…}, {…}]

十五、[...new Set(arr)]

[...new Set(arr)] 
//代码就是这么少----(其实,严格来说并不算是一种,相对于第一种方法来说只是简化了代码)

PS:有些文章提到了foreach+indexOf数组去重的方法,个人觉得都是大同小异,所以没有写上去。

下面是其他网友的补充

第一种是比较常规的方法

思路:

1.构建一个新的数组存放结果

2.for循环中每次从原数组中取出一个元素,用这个元素循环与结果数组对比

3.若结果数组中没有该元素,则存到结果数组中

Array.prototype.unique1 = function(){
 var res = [this[0]];
 for(var i = 1; i < this.length; i++){
 var repeat = false;
 for(var j = 0; j < res.length; j++){
  if(this[i] == res[j]){
  repeat = true;
  break;
  }
 }
 if(!repeat){
  res.push(this[i]);
 }
 }
 return res;
}
var arr = [1, 'a', 'a', 'b', 'd', 'e', 'e', 1, 0]
alert(arr.unique1());

第二种方法比上面的方法效率要高

思路:

1.先将原数组进行排序

2.检查原数组中的第i个元素 与 结果数组中的最后一个元素是否相同,因为已经排序,所以重复元素会在相邻位置

3.如果不相同,则将该元素存入结果数组中

Array.prototype.unique2 = function(){
 this.sort(); //先排序
 var res = [this[0]];
 for(var i = 1; i < this.length; i++){
 if(this[i] !== res[res.length - 1]){
  res.push(this[i]);
 }
 }
 return res;
}
var arr = [1, 'a', 'a', 'b', 'd', 'e', 'e', 1, 0]
alert(arr.unique2());

第二种方法也会有一定的局限性,因为在去重前进行了排序,所以最后返回的去重结果也是排序后的。如果要求不改变数组的顺序去重,那这种方法便不可取了。

第三种方法(推荐使用)

思路:

1.创建一个新的数组存放结果

2.创建一个空对象

3.for循环时,每次取出一个元素与对象进行对比,如果这个元素不重复,则把它存放到结果数组中,同时把这个元素的内容作为对象的一个属性,并赋值为1,存入到第2步建立的对象中。

说明:至于如何对比,就是每次从原数组中取出一个元素,然后到对象中去访问这个属性,如果能访问到值,则说明重复。

Array.prototype.unique3 = function(){
 var res = [];
 var json = {};
 for(var i = 0; i < this.length; i++){
 if(!json[this[i]]){
  res.push(this[i]);
  json[this[i]] = 1;
 }
 }
 return res;
}

var arr = [112,112,34,'你好',112,112,34,'你好','str','str1'];
alert(arr.unique3());

以上就是js数组去重的三种常用方法总结的详细内容,更多关于js数组去重的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
JavaScript 变量基础知识
Nov 07 Javascript
通过javascript设置css属性的代码
Dec 28 Javascript
jQuery入门问答 整理的几个常见的初学者问题
Feb 22 Javascript
Javascript中Eval函数的使用
Mar 23 Javascript
jQuery温习篇 强大的JQuery选择器
Apr 24 Javascript
JavaScript中的关键字&quot;VAR&quot;使用详解 分享
Jul 31 Javascript
javascript 判断是否是微信浏览器的方法
Oct 09 Javascript
js实现登录框鼠标拖拽效果
Mar 09 Javascript
详解微信JS-SDK选择图片遇到的坑
Aug 15 Javascript
vue项目打包部署_nginx代理访问方法详解
Sep 20 Javascript
eslint 的三大通用规则详解
May 16 Javascript
微信小程序复选框实现多选一功能过程解析
Feb 14 Javascript
JQuery的$和其它JS发生冲突的快速解决方法
Jan 24 #Javascript
js判断60秒以及倒计时示例代码
Jan 24 #Javascript
innerText 使用示例
Jan 23 #Javascript
登陆成功后自动计算秒数执行跳转
Jan 23 #Javascript
检查输入的是否是数字使用keyCode配合onkeypress事件
Jan 23 #Javascript
html dom节点操作(获取/修改/添加或删除)
Jan 23 #Javascript
解决jquery插件冲突的问题
Jan 23 #Javascript
You might like
在PHP中使用curl_init函数的说明
2010/11/02 PHP
php生成图片缩略图的方法
2015/04/07 PHP
php四种定界符详解
2017/02/16 PHP
基于PHP实现解密或加密Cloudflar邮箱保护
2020/06/24 PHP
使Ext的Template可以解析二层的json数据的方法
2007/12/22 Javascript
js+css在交互上的应用
2010/07/18 Javascript
自制轻量级仿jQuery.boxy对话框插件代码
2010/10/26 Javascript
js动态加载以及确定加载完成的代码
2011/07/31 Javascript
js 实现菜单左右滚动显示示例介绍
2013/11/21 Javascript
jquery实现点击label的同时触发文本框点击事件的方法
2015/06/05 Javascript
JS制作手机端自适应缩放显示
2015/06/11 Javascript
实例讲解javascript注册事件处理函数
2016/01/09 Javascript
JavaScript修改作用域外变量的方法
2016/03/25 Javascript
JavaScript 事件流、事件处理程序及事件对象总结
2017/04/01 Javascript
Vue2.0结合webuploader实现文件分片上传功能
2018/03/09 Javascript
Angular中使用better-scroll插件的方法
2018/03/27 Javascript
vue中的provide/inject的学习使用
2018/05/09 Javascript
AngularJS上传文件的示例代码
2018/11/10 Javascript
vue实现分页组件
2020/06/16 Javascript
Vue 列表上下过渡效果的实例代码
2019/06/25 Javascript
非常实用的jQuery代码段集锦【检测浏览器、滚动、复制、淡入淡出等】
2019/08/08 jQuery
Node4-5静态资源服务器实战以及优化压缩文件实例内容
2019/08/29 Javascript
mpvue实现小程序签到金币掉落动画(api实现)
2019/10/17 Javascript
vue项目里面引用svg文件并给svg里面的元素赋值
2020/08/17 Javascript
[00:36]DOTA2勇士令状莱恩声望物品——冥晶之厄展示
2018/05/25 DOTA
Python爬取十篇新闻统计TF-IDF
2018/01/03 Python
Python入门学习指南分享
2018/04/11 Python
Tornado Web Server框架编写简易Python服务器
2018/07/28 Python
Python面向对象之继承和多态用法分析
2019/06/08 Python
CSS3图片旋转特效(360/60/-360度)
2013/10/10 HTML / CSS
大女孩胸罩:Big Girls Bras
2016/12/15 全球购物
先进员工获奖感言
2014/08/14 职场文书
2015年手术室工作总结
2015/05/11 职场文书
2015年出纳年终工作总结
2015/05/14 职场文书
MongoDB orm框架的注意事项及简单使用
2021/06/20 MongoDB
SQL之各种join小结详细讲解
2021/08/04 MySQL