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 相关文章推荐
解析Jquery取得iframe中元素的几种方法
Jul 04 Javascript
ie8 不支持new Date(2012-11-10)问题的解决方法
Jul 31 Javascript
javascript移出节点removeChild()使用介绍
Apr 03 Javascript
jquery实现可关闭的倒计时广告特效代码
Sep 02 Javascript
Bootstrap模态框使用详解
Feb 15 Javascript
图解Javascript——作用域、作用域链、闭包
Mar 21 Javascript
AngularJS实现注册表单验证功能
Oct 16 Javascript
详解Vue组件实现tips的总结
Nov 01 Javascript
利用canvas中toDataURL()将图片转为dataURL(base64)的方法详解
Nov 20 Javascript
Vue表单及表单绑定方法
Sep 04 Javascript
通过微信公众平台获取公众号文章的方法示例
Dec 25 Javascript
JS实现简易留言板(节点操作)
Mar 16 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调用三种数据库的方法(2)
2006/10/09 PHP
PHP中cookies使用指南
2007/03/16 PHP
php中神奇的fastcgi_finish_request
2011/05/02 PHP
php数组函数序列之in_array() - 查找数组中是否存在指定值
2011/11/07 PHP
支持生僻字且自动识别utf-8编码的php汉字转拼音类
2014/06/27 PHP
php实现上传图片文件代码
2015/07/19 PHP
Yii2.0框架模型添加/修改/删除数据操作示例
2019/07/18 PHP
PHP全局使用Laravel辅助函数dd
2019/12/26 PHP
3Z版基于jquery的图片复选框(asp.net+jquery)
2010/04/12 Javascript
使用jQuery操作Cookies的实现代码
2011/10/09 Javascript
Javascript中的for in循环和hasOwnProperty结合使用
2013/06/05 Javascript
javascript引用赋值(地址传值)用法实例
2015/01/13 Javascript
浅谈Unicode与JavaScript的发展史
2015/01/19 Javascript
Java File类的常用方法总结
2015/03/18 Javascript
jQuery.trim() 函数及trim()用法详解
2015/10/26 Javascript
详解JavaScript的另类写法
2016/04/11 Javascript
JavaScript知识点总结(六)之JavaScript判断变量数据类型
2016/05/31 Javascript
js的各种排序算法实现(总结)
2016/07/23 Javascript
Bootstrap导航简单实现代码
2017/03/06 Javascript
详解Vue2.0配置mint-ui踩过的那些坑
2018/04/23 Javascript
vue路由 遍历生成复数router-link的例子
2019/10/30 Javascript
详解Python if-elif-else知识点
2018/06/11 Python
用python生成(动态彩色)二维码的方法(使用myqr库实现)
2019/06/24 Python
python每天定时运行某程序代码
2019/08/16 Python
基于python修改srt字幕的时间轴
2020/02/03 Python
python爬虫数据保存到mongoDB的实例方法
2020/07/28 Python
用CSS3写的模仿iPhone中的返回按钮
2015/04/04 HTML / CSS
玉兰油美国官网:OLAY美国
2018/10/25 全球购物
求职简历中个人的自我评价
2013/12/01 职场文书
业务员岗位职责范本
2013/12/15 职场文书
三查三看党性分析材料
2014/02/18 职场文书
超市国庆节促销方案
2014/02/20 职场文书
节约用水倡议书
2014/04/16 职场文书
反邪教学习心得体会
2016/01/15 职场文书
MySQL之PXC集群搭建的方法步骤
2021/05/25 MySQL
Go遍历struct,map,slice的实现
2021/06/13 Golang