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 计算两个整数的百分比值
Dec 26 Javascript
IE iframe的onload方法分析小结
Jan 07 Javascript
js获取光标位置和设置文本框光标位置示例代码
Jan 09 Javascript
使用js判断当前时区TimeZone是否是夏令时
Feb 23 Javascript
iframe窗口高度自适应的又一个巧妙实现思路
Apr 04 Javascript
实例分析javascript中的call()和apply()方法
Nov 28 Javascript
原生js实现百叶窗效果及原理介绍
Apr 12 Javascript
AngularJS ui-router (嵌套路由)实例
Mar 10 Javascript
JQuery animate动画应用示例
May 14 jQuery
基于JS实现前端压缩上传图片的实例代码
May 14 Javascript
如何在vue中使用百度地图添加自定义覆盖物(水波纹)
Nov 03 Javascript
详解实现vue的数据响应式原理
Jan 20 Vue.js
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通过header实现文本文件下载的代码
2010/08/08 PHP
实现PHP框架系列文章(6)mysql数据库方法
2016/03/04 PHP
浅谈php中urlencode与rawurlencode的区别
2016/09/05 PHP
php微信公众号开发之校园图书馆
2018/10/20 PHP
任意位置显示html菜单
2007/02/01 Javascript
实现JavaScript中继承的三种方式
2009/10/16 Javascript
jquery插件jSignature实现手动签名
2015/05/04 Javascript
jQuery实现鼠标经过图片变亮其他变暗效果
2015/05/08 Javascript
js与applet相互调用的方法
2016/06/22 Javascript
JQuery学习总结【一】
2016/12/01 Javascript
理解Angular的providers给Http添加默认headers
2017/07/04 Javascript
Centos7 安装Node.js10以上版本的方法步骤
2019/10/15 Javascript
[16:19]教你分分钟做大人——风暴之灵
2015/03/11 DOTA
Python的批量远程管理和部署工具Fabric用法实例
2015/01/23 Python
Python3使用TCP编写一个简易的文件下载器功能
2019/05/08 Python
ZABBIX3.2使用python脚本实现监控报表的方法
2019/07/02 Python
解决django model修改添加字段报错的问题
2019/11/18 Python
如何在python中执行另一个py文件
2020/04/30 Python
Python3爬虫中关于中文分词的详解
2020/07/29 Python
实例教程 利用html5和css3打造一款创意404页面
2014/10/20 HTML / CSS
编程用JAVA解析XML的方式
2013/07/07 面试题
大学毕业感言50字
2014/02/07 职场文书
交通事故赔偿协议书范本
2014/04/15 职场文书
奉献演讲稿范文
2014/05/21 职场文书
争先创优演讲稿
2014/09/15 职场文书
和谐家庭事迹材料
2014/12/20 职场文书
自主招生自荐信怎么写
2015/03/24 职场文书
戒赌保证书
2015/05/11 职场文书
应收账款管理制度
2015/08/06 职场文书
python process模块的使用简介
2021/05/14 Python
pyqt5打包成exe可执行文件的方法
2021/05/14 Python
my.ini优化mysql数据库性能的十个参数(推荐)
2021/05/26 MySQL
Redis分布式锁Redlock的实现
2021/08/07 Redis
vue3使用vuedraggable实现拖拽功能
2022/04/06 Vue.js
Java 超详细讲解十大排序算法面试无忧
2022/04/08 Java/Android
MySQL去除密码登录告警的方法
2022/04/20 MySQL