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 相关文章推荐
JS 面向对象的5钟写法
Jul 31 Javascript
javascript去除字符串左右两端的空格
Feb 05 Javascript
JavaScript实现图片轮播的方法
Jul 31 Javascript
angular写一个列表的选择全选交互组件的示例
Jan 22 Javascript
jquery的 filter()方法使用教程
Mar 22 jQuery
JavaScript设计模式之职责链模式应用示例
Aug 07 Javascript
微信小程序购物车、父子组件传值及calc的注意事项总结
Nov 14 Javascript
jQuery移动端跑马灯抽奖特效升级版(抽奖概率固定)实现方法
Jan 18 jQuery
vue实现路由监听和参数监听
Oct 29 Javascript
vue中的过滤器及其时间格式化问题
Apr 09 Javascript
vue-simple-uploader上传成功之后的response获取代码
Sep 07 Javascript
JS实现公告上线滚动效果
Jan 10 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
php 表单验证实现代码
2009/03/10 PHP
利用php绘制饼状图的实现代码
2013/06/07 PHP
php发送get、post请求的6种方法简明总结
2014/07/08 PHP
[原创]php token使用与验证示例【测试可用】
2017/08/30 PHP
jQuery取得select选择的文本与值的示例
2013/12/09 Javascript
jquery阻止后续事件只执行第一个事件
2014/07/24 Javascript
js实现漂浮回顶部按钮实例
2015/05/06 Javascript
在Javascript中处理字符串之big()方法的使用
2015/06/08 Javascript
基于javascript实现按圆形排列DIV元素(三)
2016/12/02 Javascript
JS简单验证上传文件类型的方法
2017/04/17 Javascript
js学习总结_轮播图之渐隐渐现版(实例讲解)
2017/07/17 Javascript
微信小程序实现选项卡效果
2018/11/06 Javascript
解决layer图标icon不加载的问题
2019/09/04 Javascript
jquery 键盘事件 keypress() keydown() keyup()用法总结
2019/10/23 jQuery
JavaScript中的函数申明、函数表达式、箭头函数
2019/12/06 Javascript
vue 函数调用加括号与不加括号的区别
2020/10/29 Javascript
Python性能优化技巧
2015/03/09 Python
详解Python在七牛云平台的应用(一)
2017/12/05 Python
pandas 小数位数 精度的处理方法
2018/06/09 Python
python 使用turtule绘制递归图形(螺旋、二叉树、谢尔宾斯基三角形)
2019/05/30 Python
python字典的setdefault的巧妙用法
2019/08/07 Python
Jupyter notebook快速入门教程(推荐)
2020/05/18 Python
给Django Admin添加验证码和多次登录尝试限制的实现
2020/07/26 Python
乌克兰移动电子产品和相关配件的在线商店:iTMag
2020/03/16 全球购物
JSF界面控制层技术
2013/06/17 面试题
酒店拾金不昧表扬信
2014/01/18 职场文书
水利水电建筑施工应届生求职信
2014/07/04 职场文书
初中家长评语和期望
2014/12/26 职场文书
小学教师师德师风自我评价
2015/03/04 职场文书
哈姆雷特读书笔记
2015/06/29 职场文书
战友聚会致辞
2015/07/28 职场文书
小学主题班会教案
2015/08/17 职场文书
PHP实现考试倒计时功能代码
2021/04/16 PHP
Python3中PyQt5简单实现文件打开及保存
2021/06/10 Python
Python+Matplotlib+LaTeX玩转数学公式
2022/02/24 Python
分享几个实用的CSS代码块
2022/06/10 HTML / CSS