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中的Array对象使用说明
Jan 17 Javascript
js+html+css实现鼠标移动div实例
Jan 30 Javascript
用js通过url传参把数据从一个页面传到另一个页面
Sep 01 Javascript
readonly和disabled属性的区别
Jul 26 Javascript
详解Bootstrap四种图片样式
Jan 04 Javascript
移动端H5开发 Turn.js实现很棒的翻书效果
Jun 20 Javascript
JS实现点击网页判断是否安装app并打开否则跳转app store
Nov 18 Javascript
Angular 4依赖注入学习教程之ClassProvider的使用(三)
Jun 04 Javascript
浅谈事件冒泡、事件委托、jQuery元素节点操作、滚轮事件与函数节流
Jul 22 jQuery
vue.js 底部导航栏 一级路由显示 子路由不显示的解决方法
Mar 09 Javascript
D3.js(v3)+react 实现带坐标与比例尺的柱形图 (V3版本)
May 09 Javascript
原生js实现弹幕效果
Nov 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
mysql limit查询优化分析
2008/11/12 PHP
PHP+MySql+jQuery实现的&quot;顶&quot;和&quot;踩&quot;投票功能
2016/05/21 PHP
PHP购物车类Cart.class.php定义与用法示例
2016/07/20 PHP
解决PHP 7编译安装错误:cannot stat ‘phar.phar’: No such file or directory
2017/02/25 PHP
PHP框架Laravel中实现supervisor执行异步进程的方法
2017/06/07 PHP
10个实用的脚本代码工具
2010/05/04 Javascript
使用jquery实现图文切换效果另加特效
2013/01/20 Javascript
js解决弹窗问题实现班级跳转DIV示例
2014/01/06 Javascript
简介JavaScript中的unshift()方法的使用
2015/06/09 Javascript
JS实现样式清新的横排下拉菜单效果
2015/10/09 Javascript
详解JavaScript逻辑And运算符
2015/12/04 Javascript
JavaScript Array对象详解
2016/03/01 Javascript
js实现倒计时及时间对象
2016/11/15 Javascript
CSS3+JavaScript实现翻页幻灯片效果
2017/06/28 Javascript
jQuery实现可兼容IE6的淡入淡出效果告警提示功能示例
2017/09/20 jQuery
详解node Async/Await 更好的异步编程解决方案
2018/05/10 Javascript
js代码规范之Eslint安装与配置详解
2018/09/08 Javascript
详解JavaScript函数callee、call、apply的区别
2019/03/08 Javascript
vue-cli3单页构建大型项目方案
2020/04/07 Javascript
浅谈React中组件逻辑复用的那些事儿
2020/05/21 Javascript
详解Python中的Cookie模块使用
2015/07/06 Python
python多行字符串拼接使用小括号的方法
2020/03/19 Python
举例讲解Python常用模块
2019/03/08 Python
django的settings中设置中文支持的实现
2019/04/28 Python
Python动态参数/命名空间/函数嵌套/global和nonlocal
2019/05/29 Python
使用Python实现Wake On Lan远程开机功能
2020/01/22 Python
Flask缓存静态文件的具体方法
2020/08/02 Python
Etam德国:内衣精品店
2019/08/25 全球购物
澳大利亚最便宜的网上药房:Chemist Warehouse
2020/01/30 全球购物
2013年高中生自我评价
2013/10/23 职场文书
五十岁生日宴会答谢词
2014/01/15 职场文书
财务内勤岗位职责
2014/04/17 职场文书
放飞梦想演讲稿200字
2014/08/26 职场文书
高中生思想道德自我评价
2015/03/09 职场文书
胡桃夹子观后感
2015/06/11 职场文书
党章学习心得体会2016
2016/01/14 职场文书