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 相关文章推荐
面向对象的Javascript之二(接口实现介绍)
Jan 27 Javascript
使用jquery读取html5 localstorage的值的方法
Jan 04 Javascript
js 字符串转换成数字的三种方法
Mar 23 Javascript
jQuery Validate验证框架经典大全
Sep 23 Javascript
自动化测试读写64位操作系统的注册表
Aug 15 Javascript
微信小程序 vidao实现视频播放和弹幕的功能
Nov 02 Javascript
bootstrap输入框组使用方法
Feb 07 Javascript
详解Vue2.x-directive的学习笔记
Jul 17 Javascript
关于JavaScript中forEach和each用法浅析
Jul 27 Javascript
js 奇葩技巧之隐藏代码
Aug 11 Javascript
浅谈Angular路由守卫
Aug 26 Javascript
vue.config.js常用配置详解
Nov 14 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
资料注册后发信小技巧
2006/10/09 PHP
一个用php3编写的简单计数器
2006/10/09 PHP
一个简单的PHP&amp;MYSQL留言板源码
2020/07/19 PHP
PHP文件注释标记及规范小结
2012/04/01 PHP
PHP实现获取ip地址的5种方法,以及插入用户登录日志操作示例
2019/02/28 PHP
ThinkPHP5.0框架实现切换数据库的方法分析
2019/10/30 PHP
php进程(线程)通信基础之System V共享内存简单实例分析
2019/11/09 PHP
javascript document.referrer 用法
2009/04/30 Javascript
JavaScript 读取元素的CSS信息的代码
2010/02/07 Javascript
jquery图片放大镜功能的实例代码
2013/03/26 Javascript
JavaScript通过join函数连接数组里所有元素的方法
2015/03/20 Javascript
js简单实现表单中点击按钮动态增加输入框数量的方法
2015/08/18 Javascript
jQuery实现垂直半透明手风琴特效代码分享
2015/08/21 Javascript
JavaScript中的this到底是什么(一)
2015/12/09 Javascript
Hammer.js+轮播原理实现简洁的滑屏功能
2016/02/02 Javascript
基于javascript实现句子翻牌网页版小游戏
2016/03/23 Javascript
JS IOS/iPhone的Safari浏览器不兼容Javascript中的Date()问题如何解决
2016/11/11 Javascript
Jquery Easyui表单组件Form使用详解(30)
2016/12/19 Javascript
JSON是什么?有哪些优点?JSON和XML的区别?
2019/04/29 Javascript
JavaScript前后端JSON使用方法教程
2020/11/23 Javascript
基于Django用户认证系统详解
2018/02/21 Python
Python实现图片添加文字
2019/11/26 Python
Python 基于FIR实现Hilbert滤波器求信号包络详解
2020/02/26 Python
Django 项目布局方法(值得推荐)
2020/03/22 Python
使paramiko库执行命令时在给定的时间强制退出功能的实现
2021/03/03 Python
分享一个H5原生form表单的checkbox特效代码
2018/02/26 HTML / CSS
澳大利亚最受欢迎的美发和美容在线商店:Catwalk
2018/12/12 全球购物
分层教学实施方案
2014/03/19 职场文书
教师节宣传方案
2014/05/23 职场文书
企业法人代表证明书
2014/09/27 职场文书
2014年党员自我剖析材料
2014/10/07 职场文书
考试作弊检讨书怎么写?
2014/12/21 职场文书
2015年幼儿园保育员工作总结
2015/04/23 职场文书
公司考勤管理制度
2015/08/04 职场文书
女性励志书籍推荐
2019/08/19 职场文书
Html5大屏数据可视化开发的实现
2021/06/11 HTML / CSS