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 相关文章推荐
Textarea根据内容自适应高度
Oct 28 Javascript
node.js中的fs.readSync方法使用说明
Dec 17 Javascript
js电话号码验证方法
Sep 28 Javascript
Node.js 条形码识别程序构建思路详解
Feb 14 Javascript
使用JQuery 加载页面时调用JS的实现方法
May 30 Javascript
easyui form validate总是返回false的原因及解决方法
Nov 07 Javascript
JS中利用swiper实现3d翻转幻灯片实例代码
Aug 25 Javascript
JavaScript 异步调用
Oct 25 Javascript
webstorm+vue初始化项目的方法
Oct 18 Javascript
JavaScript数组去重的几种方法
Apr 07 Javascript
jQuery轮播图功能制作方法详解
Dec 03 jQuery
浅谈vue权限管理实现及流程
Apr 23 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计算整个目录大小的方法
2015/06/19 PHP
适用于初学者的简易PHP文件上传类
2015/10/29 PHP
浅谈PHP发送HTTP请求的几种方式
2017/07/25 PHP
PHP观察者模式示例【Laravel框架中有用到】
2018/06/15 PHP
php提取微信账单的有效信息
2018/10/01 PHP
Node.js和PHP根据ip获取地理位置的方法
2014/03/14 Javascript
Jquery实现Div上下移动示例
2014/04/23 Javascript
ECMAScript 5中的属性描述符详解
2015/03/02 Javascript
基于jQuery 实现bootstrapValidator下的全局验证
2015/12/07 Javascript
json实现添加、遍历与删除属性的方法
2016/06/17 Javascript
Bootstrap Table的使用总结
2016/10/08 Javascript
详解jQuery中基本的动画方法
2016/12/14 Javascript
谈谈第三方App接入微信登录 解读
2016/12/27 Javascript
vue.js实现用户评论、登录、注册、及修改信息功能
2020/05/30 Javascript
详解Vue.js基于$.ajax获取数据并与组件的data绑定
2017/05/26 Javascript
vue 做移动端微信公众号采坑经验记录
2018/04/26 Javascript
Bootstrap-table自定义可编辑每页显示记录数
2018/09/07 Javascript
微信小程序入门之广告条实现方法示例
2018/12/05 Javascript
超好用的jQuery分页插件jpaginate用法示例【附源码下载】
2018/12/06 jQuery
JavaScript数组去重的几种方法
2019/04/07 Javascript
用 js 写一个 js 解释器过程详解
2019/08/02 Javascript
python处理xml文件的方法小结
2017/05/02 Python
利用numpy+matplotlib绘图的基本操作教程
2017/05/03 Python
django使用xlwt导出excel文件实例代码
2018/02/06 Python
Python编程实现从字典中提取子集的方法分析
2018/02/09 Python
Python多线程处理实例详解【单进程/多进程】
2019/01/30 Python
Python爬取阿拉丁统计信息过程图解
2020/05/12 Python
Python操作Word批量生成合同的实现示例
2020/08/28 Python
python爬虫请求头的使用
2020/12/01 Python
日本乐天德国站:Rakuten.de
2019/05/16 全球购物
MYSQL基础面试题
2012/05/13 面试题
物流管理专业自荐信
2014/06/23 职场文书
地球物理学专业推荐信
2014/09/08 职场文书
2014年医务科工作总结
2014/12/18 职场文书
2015年小学实验室工作总结
2015/07/28 职场文书
八年级作文之友谊
2019/12/02 职场文书