javascript数组去重的六种方法汇总


Posted in Javascript onAugust 16, 2015

面试前端必须准备的一个问题:怎样去掉Javascript的Array的重复项。据我所知,百度、腾讯、盛大等都在面试里出过这个题目。 这个问题看起来简单,但是其实暗藏杀机。 考的不仅仅是实现这个功能,更能看出你对计算机程序执行的深入理解。

    我总共想出了三种算法来实现这个目的:

Array.prototype.unique1 = function()
{
 var n = []; //一个新的临时数组
 for(var i = 0; i < this.length; i++) //遍历当前数组
 {
 //如果当前数组的第i已经保存进了临时数组,那么跳过,
 //否则把当前项push到临时数组里面
 if (n.indexOf(this[i]) == -1) n.push(this[i]);
 }
 return n;
}
Array.prototype.unique2 = function()
{
 var n = {},r=[]; //n为hash表,r为临时数组
 for(var i = 0; i < this.length; i++) //遍历当前数组
 {
 if (!n[this[i]]) //如果hash表中没有当前项
 {
  n[this[i]] = true; //存入hash表
  r.push(this[i]); //把当前数组的当前项push到临时数组里面
 }
 }
 return r;
}
Array.prototype.unique3 = function()
{
 var n = [this[0]]; //结果数组
 for(var i = 1; i < this.length; i++) //从第二项开始遍历
 {
 //如果当前数组的第i项在当前数组中第一次出现的位置不是i,
 //那么表示第i项是重复的,忽略掉。否则存入结果数组
 if (this.indexOf(this[i]) == i) n.push(this[i]);
 }
 return n;
}

    其中第1种和第3种方法都用到了数组的indexOf方法。此方法的目的是寻找存入参数在数组中第一次出现的位置。很显然,js引擎在实现这个方法的时候会遍历数组直到找到目标为止。所以此函数会浪费掉很多时间。 而第2中方法用的是hash表。把已经出现过的通过下标的形式存入一个object内。下标的引用要比用indexOf搜索数组快的多。

    为了判断这三种方法的效率如何,我做了一个测试程序,生成一个10000长度的随机数组成的数组,然后分别用几个方法来测试执行时间。 结果表明第二种方法远远快于其他两种方法。 但是内存占用方面应该第二种方法比较多,因为多了一个hash表。这就是所谓的空间换时间。  就是这个测试页面,你也可以去看看。

根据hpl大牛的思路,我写了第四种方法:

Array.prototype.unique4 = function()
{
 this.sort();
 var re=[this[0]];
 for(var i = 1; i < this.length; i++)
 {
 if( this[i] !== re[re.length-1])
 {
  re.push(this[i]);
 }
 }
 return re;
}

    这个方法的思路是先把数组排序,然后比较相邻的两个值。 排序的时候用的JS原生的sort方法,JS引擎内部应该是用的快速排序吧。 最终测试的结果是此方法运行时间平均是第二种方法的三倍左右,不过比第一种和第三种方法快了不少。

第五种方法

最近在做【搜索历史记录】功能也用到,开始用了 indexOf 方法,该方法在 ECMA5才有支持,对于 IE8- 就不支持了。

我们可以自己写一个函数(Array对象的方法都是定义在原型对象上的),如下:

Array.prototype.unique = function(){
  var length = this.length;
  if(length <= 1){
    return this;
  }
  if(!Array.prototype.indexOf){    
    Array.prototype.indexOf = function(item){
      var l = this.length, i = 0, r = -1;
      if(l <= 0){


 
return -1;



 }
      for(; i < l; i++){
        if(this[i] === item){
          r = i;
        }
      }
      return r;
    }
  }
  
  var result = []; //去重数组
  for(var i = 0; i < length; i++){
    if(result.indexOf(this[i]) === -1){
      result.push(this[i]);
    }
  }
  return result;
}

第六种方法

Array类型并没有提供去重复的方法,如果要把数组的重复元素干掉,那得自己想办法:

function unique(arr) {
  var result = [], isRepeated;
  for (var i = 0, len = arr.length; i < len; i++) {
    isRepeated = false;
    for (var j = 0, len = result.length; j < len; j++) {
      if (arr[i] == result[j]) {  
        isRepeated = true;
        break;
      }
    }
    if (!isRepeated) {
      result.push(arr[i]);
    }
  }
  return result;
}

总体思路是把数组元素逐个搬运到另一个数组,搬运的过程中检查这个元素是否有重复,如果有就直接丢掉。从嵌套循环就可以看出,这种方法效率极低。我们可以 用一个hashtable的结构记录已有的元素,这样就可以避免内层循环。

Javascript 相关文章推荐
类似CSDN图片切换效果脚本
Sep 17 Javascript
javascript学习之闭包分析
Dec 02 Javascript
使用Mootools动态添加Css样式表代码,兼容各浏览器
Dec 12 Javascript
js的alert弹出框出现乱码解决方案
Sep 02 Javascript
几种延迟加载JS代码的方法加快网页的访问速度
Oct 12 Javascript
从js向Action传中文参数出现乱码问题的解决方法
Dec 29 Javascript
Linux下编译安装php libevent扩展实例
Feb 14 Javascript
jquery实现鼠标经过显示下划线的渐变下拉菜单效果代码
Aug 24 Javascript
js流动式效果显示当前系统时间
May 16 Javascript
浅谈jQuery hover(over, out)事件函数
Dec 03 Javascript
vue v-for 点击当前行,获取当前行数据及event当前事件对象的操作
Sep 10 Javascript
ant design中upload组件上传大文件,显示进度条进度的实例
Oct 29 Javascript
JS+CSS实现下拉列表框美化效果(3款)
Aug 15 #Javascript
js时钟翻牌效果实现代码分享
Jul 31 #Javascript
js实现点击文本框显示日期选择器特效代码分享
May 21 #Javascript
jQuery树形下拉菜单特效代码分享
Aug 15 #Javascript
Jquery幻灯片特效代码分享--打开页面随机选择切换方式(3)
Aug 15 #Javascript
jQuery幻灯片特效代码分享--鼠标滑过按钮时切换(2)
Nov 18 #Javascript
Jquery幻灯片特效代码分享--鼠标点击按钮时切换(1)
Aug 15 #Javascript
You might like
世界上第一台立体声收音机
2021/03/01 无线电
咖啡知识大全
2021/03/03 新手入门
Php获取金书网的书名的实现代码
2010/06/11 PHP
php_screw安装使用教程(另一个PHP代码加密实现)
2014/05/29 PHP
PHP工厂模式简单实现方法示例
2018/05/23 PHP
根据分辩率调用不同的CSS.
2007/01/08 Javascript
JavaScript转换农历类实现及调用方法
2013/01/27 Javascript
从零学JSON之JSON数据结构
2014/05/19 Javascript
JavaScript函数参数使用带参数名的方式赋值传入的方法
2015/03/19 Javascript
JavaScript实现动画打开半透明提示层的方法
2015/04/21 Javascript
一个字符串中出现次数最多的字符 统计这个次数【实现代码】
2016/04/29 Javascript
Javascript使用uploadify来实现多文件上传
2016/11/16 Javascript
JavaScript数组的5种迭代方法
2017/09/29 Javascript
bootstrap时间控件daterangepicker使用方法及各种小bug修复
2017/10/25 Javascript
简单的Vue异步组件实例Demo
2017/12/27 Javascript
jQuery实现的点击按钮改变样式功能示例
2018/07/21 jQuery
详解微信小程序的不同函数调用的几种方法
2019/05/08 Javascript
three.js欧拉角和四元数的使用方法
2020/07/26 Javascript
Electron+vue从零开始打造一个本地播放器的方法示例
2020/10/27 Javascript
让Python代码更快运行的5种方法
2015/06/21 Python
对python遍历文件夹中的所有jpg文件的实例详解
2018/12/08 Python
Python编写打字训练小程序
2019/09/26 Python
python图形用户接口实例详解
2019/12/16 Python
HTML5 语音搜索只需一句代码
2013/01/03 HTML / CSS
美国婚礼和派对礼品网站:Kate Aspen(新娘送礼会、迎婴派对)
2018/03/28 全球购物
如果NULL和0作为空指针常数是等价的,那我到底该用哪一个
2014/09/16 面试题
人力资源管理专业应届生求职信
2013/09/28 职场文书
汽车运用工程毕业生自荐信
2013/10/29 职场文书
计算机系毕业生推荐信
2013/11/06 职场文书
职专应届生求职信
2013/11/16 职场文书
《小白兔和小灰兔》教学反思
2014/02/18 职场文书
会计自荐信范文
2014/03/09 职场文书
廉洁使者实施方案
2014/03/29 职场文书
委托证明书
2014/09/17 职场文书
个人自我剖析材料
2014/09/30 职场文书
坎儿井导游词
2015/02/09 职场文书